设计模式——责任链模式

责任链模式 (Chain of Responsibility Pattern)

什么是责任链模式?

责任链模式是一种行为型设计模式,它允许你将请求沿着处理者链传递,直到有一个处理者能够处理该请求。

简单来说:责任链模式就是"踢皮球",一个处理不了就传给下一个。

生活中的例子

想象一下:

  • 审批流程:员工请假 → 部门经理 → 人事经理 → 总经理
  • 客服系统:一级客服 → 二级客服 → 技术支持
  • 异常处理:try → catch → finally

为什么需要责任链模式?

传统方式的问题

java 复制代码
// 使用if-else处理
if (level == 1) {
    manager1.handle();
} else if (level == 2) {
    manager2.handle();
} else if (level == 3) {
    manager3.handle();
}

问题

  1. 代码臃肿:大量if-else导致代码臃肿
  2. 难以扩展:新增处理者需要修改代码
  3. 耦合度高:客户端与所有处理者耦合

责任链模式的优势

java 复制代码
// 使用责任链
handler1.setNext(handler2);
handler2.setNext(handler3);
handler1.handle(request);

优势

  1. 解耦合:发送者和接收者解耦
  2. 灵活扩展:可以灵活地添加或删除处理者
  3. 动态组合:可以动态地组合处理者链

责任链模式的结构

复制代码
┌─────────────────────┐
│      Handler        │  处理者接口
├─────────────────────┤
│ - next: Handler     │
│ + setNext(): void   │
│ + handle(): void    │
└──────────┬──────────┘
           │ 继承
           ├──┬──────────────────┬──────────────┐
           │                    │              │
┌──────────┴──────┐  ┌───────────┴───────┐  ┌───┴────────┐
│ ConcreteHandler1│  │ ConcreteHandler2 │  │ ...       │  具体处理者
├─────────────────┤  ├───────────────────┤  ├────────────┤
│ + handle()      │  │ + handle()        │  │            │
└─────────────────┘  └───────────────────┘  └────────────┘

代码示例

1. 定义处理者接口

java 复制代码
/**
 * 抽象处理者:请假审批
 */
public abstract class LeaveApproval {
    protected LeaveApproval next;
    protected String name;
    
    public LeaveApproval(String name) {
        this.name = name;
    }
    
    public void setNext(LeaveApproval next) {
        this.next = next;
    }
    
    /**
     * 处理请假请求
     * @param days 请假天数
     */
    public abstract void handle(int days);
}

2. 定义具体处理者

java 复制代码
/**
 * 具体处理者:主管
 */
public class Supervisor extends LeaveApproval {
    public Supervisor(String name) {
        super(name);
    }
    
    @Override
    public void handle(int days) {
        if (days <= 3) {
            System.out.println(name + "批准了" + days + "天的请假");
        } else if (next != null) {
            next.handle(days);
        } else {
            System.out.println("无人能处理" + days + "天的请假");
        }
    }
}

/**
 * 具体处理者:经理
 */
public class Manager extends LeaveApproval {
    public Manager(String name) {
        super(name);
    }
    
    @Override
    public void handle(int days) {
        if (days <= 7) {
            System.out.println(name + "批准了" + days + "天的请假");
        } else if (next != null) {
            next.handle(days);
        } else {
            System.out.println("无人能处理" + days + "天的请假");
        }
    }
}

/**
 * 具体处理者:总监
 */
public class Director extends LeaveApproval {
    public Director(String name) {
        super(name);
    }
    
    @Override
    public void handle(int days) {
        if (days <= 14) {
            System.out.println(name + "批准了" + days + "天的请假");
        } else if (next != null) {
            next.handle(days);
        } else {
            System.out.println("无人能处理" + days + "天的请假");
        }
    }
}

/**
 * 具体处理者:CEO
 */
public class CEO extends LeaveApproval {
    public CEO(String name) {
        super(name);
    }
    
    @Override
    public void handle(int days) {
        if (days <= 30) {
            System.out.println(name + "批准了" + days + "天的请假");
        } else {
            System.out.println("无人能处理" + days + "天的请假");
        }
    }
}

3. 使用责任链

java 复制代码
/**
 * 责任链模式测试类
 * 演示如何使用责任链模式处理请假审批
 */
public class ChainOfResponsibilityTest {
    
    public static void main(String[] args) {
        System.out.println("=== 责任链模式测试 ===\n");
        
        // 创建处理者
        LeaveApproval supervisor = new Supervisor("主管");
        LeaveApproval manager = new Manager("经理");
        LeaveApproval director = new Director("总监");
        LeaveApproval ceo = new CEO("CEO");
        
        // 设置责任链
        supervisor.setNext(manager);
        manager.setNext(director);
        director.setNext(ceo);
        
        // 测试不同天数的请假
        System.out.println("--- 请假1天 ---");
        supervisor.handle(1);
        
        System.out.println("\n--- 请假3天 ---");
        supervisor.handle(3);
        
        System.out.println("\n--- 请假7天 ---");
        supervisor.handle(7);
        
        System.out.println("\n--- 请假15天 ---");
        supervisor.handle(15);
        
        System.out.println("\n--- 请假35天 ---");
        supervisor.handle(35);
        
        System.out.println("\n=== 责任链模式的优势 ===");
        System.out.println("1. 解耦合:发送者和接收者解耦");
        System.out.println("2. 灵活扩展:可以灵活地添加或删除处理者");
        System.out.println("3. 动态组合:可以动态地组合处理者链");
        System.out.println("4. 简化代码:简化客户端代码");
        
        System.out.println("\n=== 实际应用场景 ===");
        System.out.println("1. 审批流程:请假审批、报销审批");
        System.out.println("2. 异常处理:异常处理链");
        System.out.println("3. 日志处理:日志处理链");
        System.out.println("4. 事件处理:事件处理链");
    }
}

责任链模式的优点

  1. 解耦合:发送者和接收者解耦
  2. 灵活扩展:可以灵活地添加或删除处理者
  3. 动态组合:可以动态地组合处理者链
  4. 简化代码:简化客户端代码

责任链模式的缺点

  1. 性能问题:请求可能沿着链传递多次
  2. 调试困难:难以追踪请求的处理过程
  3. 链断裂:如果链断裂,请求可能无法被处理

适用场景

  1. 多个处理者:有多个对象可以处理请求
  2. 不确定处理者:不确定哪个对象可以处理请求
  3. 动态指定:需要动态指定处理者

常见应用场景

  • 审批流程:请假审批、报销审批
  • 异常处理:异常处理链
  • 日志处理:日志处理链

使用建议

  • 多个处理者:使用责任链模式
  • 不确定处理者:使用责任链模式
  • 单一处理者:直接使用即可

注意事项

⚠️ 责任链模式虽然有用,但要注意:

  • 不要让链太长,影响性能
  • 确保链不会断裂
相关推荐
杨充20 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充20 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充20 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充20 小时前
2.面向对象的特性
设计模式
杨充20 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充20 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充20 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式