重构手法——函数行为重塑类 | 语意 | 用状态/策略替换类型代码

63 阅读2分钟

简介

"用状态/策略替换类型代码"是消除条件逻辑的高级重构手法。通过将类型相关的行为委托给状态对象或策略对象,可以实现运行时行为切换,提高系统的扩展性和可维护性。

针对的症状(代码坏味道)

  • 存在控制行为的状态类型代码
  • 需要动态切换对象行为
  • 状态转换逻辑复杂且分散
  • 新增状态需要修改多处条件判断

用状态/策略替换类型代码的详细步骤

  1. 识别状态依赖行为
    • 查找基于类型代码的条件分支
    • 标记状态转换触发点
  2. 创建状态接口
    • 定义公共行为方法
    • 声明状态转换方法
  3. 实现具体状态类
    • 为每个状态创建实现类
    • 迁移相关行为逻辑
  4. 委托上下文类
    • 在原始类中持有状态引用
    • 将请求委托给状态对象

示例

重构前代码:

class Order {
    private String state = "NEW";

    void cancel() {
        if (state.equals("NEW")) {
            state = "CANCELED";
        } else if (state.equals("PAID")) {
            refund();
            state = "CANCELED";
        }
    }
}

重构步骤:

  1. 创建状态接口:

    interface OrderState {
        void cancel(Order order);
    }
    
  2. 实现具体状态:

    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());
        }
    }
    
  3. 重构Order类:

    class Order {
        private OrderState state = new NewState();
    
        void cancel() {
            state.cancel(this);
        }
    
        void changeState(OrderState newState) {
            this.state = newState;
        }
    }
    

练习

基础练习题

  1. 简单状态替换

    // 重构前
    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;
        }
    }
    

进阶练习题

  1. 带参数的策略

    // 重构前
    class PaymentProcessor {
        private String type; // "CREDIT", "PAYPAL"
    
        void process(double amount) {
            if (type.equals("CREDIT")) {
                chargeCreditCard(amount);
            } else {
                processPaypal(amount);
            }
        }
    }
    

综合拓展练习题

  1. 复合状态系统

    // 重构前
    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);
            }
        }
    }
    

代码审查要点

  1. 优点:

    • 消除条件判断语句
    • 支持开闭原则
    • 集中状态转换逻辑
  2. 潜在问题:

    • 控制状态对象数量
    • 保持上下文精简
    • 注意状态生命周期管理