简介
"删除子类"(Remove Subclass)重构手法用于简化过度设计的继承体系。当子类差异不足以维持独立存在时,应该将其合并到父类中并用字段区分不同行为。
典型代码坏味道
- 子类仅覆盖少量方法
- 子类间差异仅由少量字段决定
- 存在仅用于创建对象的子类
- 子类方法抛出UnsupportedOperationException
重构步骤
-
识别冗余子类
- 找到行为差异极小的子类
- 分析子类特有的属性和方法
- 确认客户端创建方式
-
迁移子类特性
- 在父类中添加类型标识字段
- 将子类方法提升到父类
- 用条件逻辑替代多态调用
-
调整对象创建
- 用工厂方法替代构造函数
- 修改客户端实例化代码
- 处理遗留的子类引用
-
验证与测试
- 检查类型相关条件语句
- 验证多态行为一致性
- 确保序列化兼容性
示例
重构前:
abstract class Bird {
abstract String getCall();
}
class Sparrow extends Bird {
String getCall() {
return "Chirp";
}
}
class Owl extends Bird {
String getCall() {
return "Hoot";
}
}
重构后:
class Bird {
private BirdType type;
Bird(BirdType type) {
this.type = type;
}
String getCall() {
return type == BirdType.OWL ? "Hoot" : "Chirp";
}
}
enum BirdType {SPARROW, OWL}
专项练习
基础练习
-
重构图形类型
abstract class Shape { abstract double area(); } class Circle extends Shape { double area() { /* 实现 */ } } class Square extends Shape { double area() { /* 实现 */ } }
进阶练习
-
处理复杂继承体系
abstract class Database { abstract Query createQuery(); } class MySQL extends Database { Query createQuery() { /* MySQL实现 */ } } class PostgreSQL extends Database { Query createQuery() { /* PostgreSQL实现 */ } }
代码审查清单
优势验证
- 类数量减少50%以上
- 消除不必要的类型转换
- 简化对象创建流程
风险提示
- 可能引入条件判断复杂度
- 需要修改客户端代码
- 影响现有的反射操作