责任链模式 (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();
}
问题:
- 代码臃肿:大量if-else导致代码臃肿
- 难以扩展:新增处理者需要修改代码
- 耦合度高:客户端与所有处理者耦合
责任链模式的优势
java
// 使用责任链
handler1.setNext(handler2);
handler2.setNext(handler3);
handler1.handle(request);
优势:
- 解耦合:发送者和接收者解耦
- 灵活扩展:可以灵活地添加或删除处理者
- 动态组合:可以动态地组合处理者链
责任链模式的结构
┌─────────────────────┐
│ 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. 事件处理:事件处理链");
}
}
责任链模式的优点
- 解耦合:发送者和接收者解耦
- 灵活扩展:可以灵活地添加或删除处理者
- 动态组合:可以动态地组合处理者链
- 简化代码:简化客户端代码
责任链模式的缺点
- 性能问题:请求可能沿着链传递多次
- 调试困难:难以追踪请求的处理过程
- 链断裂:如果链断裂,请求可能无法被处理
适用场景
- 多个处理者:有多个对象可以处理请求
- 不确定处理者:不确定哪个对象可以处理请求
- 动态指定:需要动态指定处理者
常见应用场景
- 审批流程:请假审批、报销审批
- 异常处理:异常处理链
- 日志处理:日志处理链
使用建议
- 多个处理者:使用责任链模式
- 不确定处理者:使用责任链模式
- 单一处理者:直接使用即可
注意事项
⚠️ 责任链模式虽然有用,但要注意:
- 不要让链太长,影响性能
- 确保链不会断裂