简介
"用状态/策略替换类型代码"是消除条件逻辑的高级重构手法。通过将类型相关的行为委托给状态对象或策略对象,可以实现运行时行为切换,提高系统的扩展性和可维护性。
针对的症状(代码坏味道)
- 存在控制行为的状态类型代码
- 需要动态切换对象行为
- 状态转换逻辑复杂且分散
- 新增状态需要修改多处条件判断
用状态/策略替换类型代码的详细步骤
- 识别状态依赖行为
- 查找基于类型代码的条件分支
- 标记状态转换触发点
- 创建状态接口
- 定义公共行为方法
- 声明状态转换方法
- 实现具体状态类
- 为每个状态创建实现类
- 迁移相关行为逻辑
- 委托上下文类
- 在原始类中持有状态引用
- 将请求委托给状态对象
示例
重构前代码:
class Order {
private String state = "NEW";
void cancel() {
if (state.equals("NEW")) {
state = "CANCELED";
} else if (state.equals("PAID")) {
refund();
state = "CANCELED";
}
}
}
重构步骤:
-
创建状态接口:
interface OrderState { void cancel(Order order); } -
实现具体状态:
class NewState implements OrderState { public void cancel(Order order) { order.changeState(new CanceledState()); } } class PaidState implements OrderState { public void cancel(Order order) { order.refund(); order.changeState(new CanceledState()); } } -
重构Order类:
class Order { private OrderState state = new NewState(); void cancel() { state.cancel(this); } void changeState(OrderState newState) { this.state = newState; } }
练习
基础练习题
-
简单状态替换
// 重构前 class Fan { private int mode = 0; // 0=off, 1=low, 2=high void switchMode() { if (mode == 0) mode = 1; else if (mode == 1) mode = 2; else mode = 0; } }
进阶练习题
-
带参数的策略
// 重构前 class PaymentProcessor { private String type; // "CREDIT", "PAYPAL" void process(double amount) { if (type.equals("CREDIT")) { chargeCreditCard(amount); } else { processPaypal(amount); } } }
综合拓展练习题
-
复合状态系统
// 重构前 class Elevator { private String state = "IDLE"; void handleRequest(int floor) { if (state.equals("IDLE")) { moveTo(floor); state = "MOVING"; } else if (state.equals("MOVING")) { addStop(floor); } } }
代码审查要点
-
优点:
- 消除条件判断语句
- 支持开闭原则
- 集中状态转换逻辑
-
潜在问题:
- 控制状态对象数量
- 保持上下文精简
- 注意状态生命周期管理