简介
"上移构造函数体"(Pull Up Constructor Body)重构手法用于消除子类构造函数中的重复初始化逻辑。当多个子类在构造函数中执行相同的初始化操作时,可以将这些公共逻辑移动到父类构造函数中。
典型代码坏味道
- 子类构造函数包含相同的字段初始化代码
- 父类缺乏必要的初始化逻辑
- 重复的对象状态设置代码
重构步骤
-
识别重复逻辑
- 找到子类构造函数中的相同代码块
- 确认这些逻辑的通用性
- 检查父类构造函数是否已存在类似逻辑
-
创建父类构造函数
- 在父类中定义受保护/公共的构造函数
- 将公共初始化逻辑移至父类
- 使用模板方法模式处理差异点(如需)
-
调整子类实现
- 使用super()调用父类构造函数
- 保留子类特有的初始化逻辑
- 删除重复代码
-
验证与测试
- 确保继承链中的初始化顺序
- 验证final字段的正确初始化
- 检查多态方法的调用时机
示例
重构前:
```java
class Engineer extends Employee {
private String skillSet;
public Engineer(String name, String skillSet) {
super(name);
this.skillSet = skillSet;
initializeEquipment(); // 公共初始化方法
setupWorkstation(); // 公共初始化方法
}
}
class Manager extends Employee {
private int teamSize;
public Manager(String name, int teamSize) {
super(name);
this.teamSize = teamSize;
initializeEquipment(); // 公共初始化方法
setupWorkstation(); // 公共初始化方法
}
}
```
重构后:
abstract class Employee {
protected Employee(String name) {
initializeEquipment();
setupWorkstation();
}
private void initializeEquipment() { /* 公共初始化逻辑 */ }
private void setupWorkstation() { /* 公共初始化逻辑 */ }
}
class Engineer extends Employee {
private String skillSet;
public Engineer(String name, String skillSet) {
super(name);
this.skillSet = skillSet;
}
}
class Manager extends Employee {
private int teamSize;
public Manager(String name, int teamSize) {
super(name);
this.teamSize = teamSize;
}
}
专项练习
基础练习
-
重构车辆类继承体系
class Car extends Vehicle { public Car(String model, int fuelCapacity) { super(model); this.fuelCapacity = fuelCapacity; checkSafetySystem(); // 公共方法 calibrateEngine(); // 公共方法 } } class Truck extends Vehicle { public Truck(String model, int cargoCapacity) { super(model); this.cargoCapacity = cargoCapacity; checkSafetySystem(); // 公共方法 calibrateEngine(); // 公共方法 } }
进阶练习
-
跨层级构造函数重构
class Android extends MobileOS { public Android(String version) { super(version); loadKernelModules(); initFileSystem(); startRuntimeEnvironment(); } } class IOS extends MobileOS { public IOS(String version) { super(version); loadKernelModules(); initFileSystem(); configureSandbox(); } }
代码审查清单
优势验证
- 子类构造函数代码量减少50%以上
- 公共初始化逻辑集中维护
- 保证父类状态正确性
风险提示
- 可能破坏子类初始化顺序
- 父类构造函数异常处理复杂度增加
- 多线程环境下初始化竞态条件