Kotlin纯数据类与带业务逻辑普通类选型及Code A/B方案咨询
先聊纯数据类vs带业务逻辑的普通类
没有谁比谁更优,核心看职责边界:
- 纯数据类:它的唯一使命就是「承载数据」——Kotlin自动生成equals、hashCode、toString、copy这些方法,序列化、传递数据特别省心。适合做DTO(接口返回)、数据库实体、配置参数这种只需要存数据,不需要做操作的场景。
- 带业务逻辑的普通类:当数据和操作强绑定的时候,把它们封装在一起更合理。比如一个
User类,它的changePassword()方法本身就依赖userId、currentPassword这些属性,放在类里既符合面向对象的「封装」原则,调用起来也更直观。
再对比你的Code A和Code B
咱们拆解两个方案的优劣势:
Code A:纯数据类+外部Helper
- 优点:严格遵循「单一职责原则」,数据类只管存数据,蓝牙操作逻辑全在Helper里,解耦性拉满。以后如果蓝牙设置逻辑要改(比如加权限判断),直接改Helper就行,完全不用碰数据类。
- 缺点:正如你说的,调用代码太啰嗦——
aBluetoothDef?.let{BluetoothHelper(mContext).setBluetooth(it)},每次调用都要写一遍Helper实例化和方法调用,扩展性差,要是以后加个resetBluetooth(),又要写一遍类似的模板代码。
Code B:数据类中添加业务函数
- 优点:调用体验极佳!
aBluetoothDef?.set(mContext),直接告诉数据类「你去执行设置操作」,代码简洁直观,符合面向对象的「命令式调用」思维。而且Kotlin本身允许给数据类添加成员函数,语法上完全合规。 - 缺点:你担心的「数据与业务逻辑耦合」确实存在。如果这个
BluetoothDef以后要用到其他场景(比如仅用来展示蓝牙配置,不需要执行设置),那set()方法就成了冗余代码;要是以后蓝牙操作逻辑依赖的组件变了(比如不用BluetoothHelper改用BluetoothManager),还得修改数据类,违反了「开闭原则」——对扩展开放,对修改关闭。
最优推荐:用Kotlin扩展函数折中
其实你完全可以兼顾两者的优点——用Kotlin扩展函数把业务逻辑和数据类解耦,同时保留简洁的调用方式:
// 纯数据类,仅负责承载数据 data class BluetoothDef(val deviceName: String, val isEnabled: Boolean) // 把set操作写成BluetoothDef的扩展函数,放在蓝牙业务相关文件中 fun BluetoothDef.set(context: Context) { BluetoothHelper(context).setBluetooth(this) }
这样做的好处:
- 数据类依然纯净,无业务逻辑耦合,复用性拉满;
- 调用时还是
aBluetoothDef?.set(mContext),和Code B一样简洁; - 所有蓝牙相关操作集中在扩展函数里,和Code A的Helper一样好维护,以后改逻辑只动扩展函数就行。
二选一的拍板建议
如果真的只能在Code A和Code B里选:
- 要是
set()是BluetoothDef的核心固有行为(比如这个类就是专门用来描述蓝牙配置并执行设置的),那选Code B没问题,这种耦合是合理的; - 要是
set()只是这个数据类的一个「附加操作」,以后可能还有其他不同操作,那选Code A,或者直接用扩展函数(强烈推荐后者)。
内容的提问来源于stack exchange,提问作者HelloCW
相关产品推荐
相关产品推荐

