简介
"下移字段"(Push Down Field)重构手法用于处理父类中存在仅被部分子类使用的字段。当某个字段在父类中定义但实际只被少数子类使用时,将其移至真正需要该字段的子类。
典型代码坏味道
- 父类字段被少数子类使用
- 子类中存在冗余的字段定义
- 父类字段在多数子类中被设为null或默认值
重构步骤
-
识别字段使用范围
- 找到父类中未被所有子类使用的字段
- 分析字段在各子类中的访问模式
- 检查字段初始化方式的差异
-
在子类中声明字段
- 在需要该字段的子类中创建相同字段
- 调整访问修饰符(通常为protected)
- 保持父类现有构造函数不变
-
移除父类字段
- 删除父类中的冗余字段声明
- 修改父类中直接访问该字段的代码
- 处理可能存在的继承链访问
-
验证与测试
- 检查序列化兼容性
- 验证反射操作的字段存在性
- 确保数据库映射完整性
示例
重构前:
abstract class Vehicle {
protected int wingCount; // 仅飞机类需要
// 其他公共字段...
}
class Airplane extends Vehicle {
void fly() {
System.out.println("Flying with " + wingCount + " wings");
}
}
class Car extends Vehicle {
// wingCount 字段在此类中无用
}
重构后:
abstract class Vehicle {
// 其他公共字段...
}
class Airplane extends Vehicle {
protected int wingCount;
void fly() {
System.out.println("Flying with " + wingCount + " wings");
}
}
class Car extends Vehicle {
// 不再包含无用字段
}
专项练习
基础练习
-
重构动物类继承体系
abstract class Animal { protected int hornCount; // 仅山羊类需要 } class Goat extends Animal { void showHorns() { System.out.println(hornCount + " horns"); } } class Duck extends Animal { // hornCount 字段在此类中无用 }
进阶练习
-
多层级字段下移
abstract class Database { protected NoSQLConfig nosqlConfig; // 仅NoSQL子类需要 } class SQLDatabase extends Database { // 不需要NoSQL配置 } class MongoDB extends Database { void setup() { nosqlConfig.applySettings(); } }
代码审查清单
优势验证
- 父类字段冗余度降低70%以上
- 子类字段使用率提升至100%
- 消除不必要的默认值初始化
风险提示
- 可能破坏使用父类类型的客户端代码
- 需要同步修改关联的工厂方法
- 影响使用反射获取字段的逻辑