简介
"用子类替换类型代码"是实现多态行为的关键重构手法。通过将类型标识符转换为子类层次,可以消除条件判断逻辑,提高代码的可扩展性和可维护性。
针对的症状(代码坏味道)
- 使用枚举或字符串表示对象类型
- 存在基于类型代码的条件分支
- 需要为不同类型添加差异化行为
- 类型代码影响对象创建方式
用子类替换类型代码的详细步骤
- 识别类型代码
- 查找表示类型的字段
- 标记相关条件逻辑
- 创建子类层次
- 为每个类型代码创建子类
- 使用工厂方法封装创建逻辑
- 迁移类型行为
- 将条件逻辑移至子类
- 使用多态替代类型判断
- 移除类型字段
- 删除原始类型代码字段
- 调整类型相关方法
示例
重构前代码:
class Employee {
static final int ENGINEER = 0;
static final int MANAGER = 1;
private int type;
Employee(int type) {
this.type = type;
}
double getBonus() {
return type == ENGINEER ? 1000 : 2000;
}
}
重构步骤:
-
创建抽象子类:
abstract class Employee { abstract double getBonus(); static Employee create(int type) { return switch (type) { case ENGINEER -> new Engineer(); case MANAGER -> new Manager(); default -> throw new IllegalArgumentException(); }; } } -
实现具体子类:
class Engineer extends Employee { double getBonus() { return 1000; } } class Manager extends Employee { double getBonus() { return 2000; } }
练习
基础练习题
-
简单类型子类化
// 重构前 class Product { static final int BOOK = 0; private int type; }
进阶练习题
-
复杂行为迁移
// 重构前 class Order { private String status; // "NEW", "PAID" boolean canCancel() { return "NEW".equals(status); } }
综合拓展练习题
-
多类型系统
// 重构前 class Vehicle { static final int CAR = 0; static final int TRUCK = 1; double calculateTax() { return this.type == CAR ? 0.1 : 0.2; } }
代码审查要点
-
优点:
- 消除条件判断逻辑
- 支持开闭原则
- 提高代码可读性
-
潜在问题:
- 控制子类数量
- 保持工厂方法简洁
- 注意类型系统扩展成本