差异只剩数据就撤销子类
当子类的差异只剩一点数据或极少量分支时,例如只是换了一个字段值或一个方法返回值,继承带来的复杂度就不值得了:改用字段、枚举或委托表达同样的差异,类数量减少、结构更直白,序列化与测试也跟着变简单。
基本信息
| 信号 | 子类只改构造或单个方法,分支旋钮其实是数据 |
|---|---|
| 做法 | 字段或枚举替代,也可以改为委托对象 |
| 前提 | 没有外部代码按子类类型判断 |
| 配套 | 动手前后都要全局检索类型引用 |
典型使用场景
- 枚举化:若干子类只是同一字段取不同值,例如角色、级别、状态
- 字段化:子类的唯一区别就是构造参数,用字段承接即可
- 委托化:差异未来还会继续增长时,改成持有策略对象的委托字段
- 继承体系收尾:多轮重构后只剩一个子类,直接合并回父类
- 序列化简化:去掉类名参与的类型标识,存储与接口更稳定
形态示意
形态示意
# 之前:子类只是换了一个方法或一段构造参数
class Engineer extends Person # 唯一区别是角色取值
class Manager extends Person
# 之后:用字段表达差异,类数量收敛
class Person
field name
field role # role 是数据而不是类型撤销前的检查项
| 检查项 | 为什么要查 | 怎么查 |
|---|---|---|
| 类型判断 | 外部代码可能按类型走不同分支 | 全局检索子类名与类型判断语句 |
| 序列化 | 存储或协议里可能写入类名 | 检索序列化配置与历史数据字段 |
| 工厂与注册表 | 创建点可能按类型映射 | 检索实例化该子类的位置 |
| 测试替身 | 测试可能依赖具体子类做桩 | 检索测试代码里的子类引用 |
推荐顺序:先把所有按类型分派的逻辑收敛到工厂或一张映射表,再删除子类。否则删到一半会出现大量条件判断散落在调用方,重构被迫回退。
差异只是暂时相同时要谨慎合并:若两个子类未来会真正分化,合并后还得重新拆类;判断依据是业务上是否真有独立演化的可能,而不是当前代码看起来像。