简介
"保留整个对象"(Preserve Whole Object)重构手法通过传递完整对象替代多个单独参数,解决数据泥团(Data Clumps)问题。当方法需要从同一对象获取多个属性时,直接传递该对象可提高代码内聚性。
典型代码坏味道
- 方法参数列表包含多个来自同一对象的属性
- 重复的对象属性获取操作
- 频繁的对象解构操作
重构步骤
-
识别参数关联
- 找到参数列表中来自同一对象的属性组
- 确认这些属性在方法中的使用方式
- 检查对象是否包含完整上下文信息
-
重构方法签名
- 用对象参数替换多个独立属性
- 保持原始方法作为兼容层(可选)
- 更新方法内部访问方式
-
更新调用链
- 修改所有调用点传递完整对象
- 处理多层嵌套调用中的参数传递
- 移除不必要的属性获取代码
-
验证与测试
- 确保对象在调用链中的可用性
- 验证null对象处理逻辑
- 检查继承体系中的方法覆盖
示例
原始代码:
public class Room {
public boolean withinPlan(HeatingPlan plan) {
int low = daysTempRange().getLow();
int high = daysTempRange().getHigh();
return plan.withinRange(low, high);
}
}
class HeatingPlan {
public boolean withinRange(int low, int high) {
return low >= _range.getLow() && high <= _range.getHigh();
}
}
重构后的代码:
public class Room {
public boolean withinPlan(HeatingPlan plan) {
return plan.withinRange(daysTempRange());
}
}
class HeatingPlan {
public boolean withinRange(TempRange roomRange) {
return roomRange.getLow() >= _range.getLow()
&& roomRange.getHigh() <= _range.getHigh();
}
}
专项练习
基础练习
-
用户信息参数重构
public class UserService { public void sendWelcomeEmail(String firstName, String email, LocalDate joinDate) { // 发送欢迎邮件逻辑... } // 调用方式:sendWelcomeEmail(user.getFirstName(), user.getEmail(), user.getJoinDate()); }
进阶练习
-
订单处理流程重构
public class OrderValidator { public boolean isValid(String orderId, double totalAmount, int itemCount, LocalDateTime createTime) { // 验证订单有效性逻辑... } }
综合练习
-
跨系统数据同步
public class DataSync { public void syncProductInfo(int productId, String sku, BigDecimal price, int stock) { // 同步商品信息到外部系统... } }
代码审查清单
优势验证
- 参数列表长度减少30%以上
- 相关属性修改只需在对象中完成
- 方法签名更清晰表达业务意图
风险提示
- 可能引入不必要的对象依赖
- 需要保证对象在调用链中的生命周期
- 可能违反迪米特法则(Law of Demeter)