一、定义
责任链模式将多个处理器(Handler)对象连接成一条链,每个处理器决定是否处理请求或将请求传递给链上的下一个处理器。这样可将请求的发送者与处理者解耦,实现请求沿链式结构传递。
通俗理解:一个请求来了,在一条处理链上传递,每个节点看看要不要处理,不处理就交给下一个。
二、适用场景
- 有多个对象可以处理同一请求,处理者之间彼此无关;
- 请求的处理流程具有顺序性,但具体执行节点可灵活配置;
- 需要动态添加、删除或重组处理逻辑;
- 替代嵌套的 if-else 或 switch-case 判断逻辑;
三、核心角色
角色 | 说明 |
Handler(抽象处理者) | 定义处理请求的接口,并持有下一个处理者的引用 |
ConcreteHandler | 具体处理者,处理自己负责的逻辑,或将请求传给下一个处理者 |
Client(客户端) | 创建责任链,并触发请求从第一个处理者开始处理 |
四、UML 类图(UML Diagram)
+-----------------+
| Handler |
|-----------------|
| - next: Handler |
| + setNext() |
| + handle() |
+-----------------+
▲
|
+----------------------+
| ConcreteHandlerA |
+----------------------+
| + handle() |
+----------------------+
▲
|
+----------------------+
| ConcreteHandlerB |
+----------------------+
...
▲
|
+----------------------+
| Client |
+----------------------+
五、真实业务场景示例
场景说明:
构建一个请假审批系统,员工请假时,需要经过组长 → 经理 → 总监的审批。不同天数由不同角色审批,比如:
- 请假 ≤ 1 天,组长审批;
- 1 < 请假 ≤ 3 天,经理审批;
- 小于 7 天,总监审批;
1. 抽象处理器类(Handler 角色)
// Handler:抽象处理器
public abstract class Approver {
protected Approver next; // 下一个处理者
public void setNext(Approver next) {
this.next = next;
}
public abstract void handleRequest(int leaveDays);
}
2. 具体处理器类(ConcreteHandler 角色)
// ConcreteHandler:组长审批
public class TeamLeader extends Approver {
@Override
public void handleRequest(int leaveDays) {
if (leaveDays <= 1) {
System.out.println("组长批准 " + leaveDays + " 天的请假");
} else if (next != null) {
next.handleRequest(leaveDays);
} else {
System.out.println("无法处理请求");
}
}
}
// ConcreteHandler:经理审批
public class Manager extends Approver {
@Override
public void handleRequest(int leaveDays) {
if (leaveDays <= 3) {
System.out.println("经理批准 " + leaveDays + " 天的请假");
} else if (next != null) {
next.handleRequest(leaveDays);
} else {
System.out.println("无法处理请求");
}
}
}
// ConcreteHandler:总监审批
public class Director extends Approver {
@Override
public void handleRequest(int leaveDays) {
if (leaveDays <= 7) {
System.out.println("总监批准 " + leaveDays + " 天的请假");
} else {
System.out.println("请假天数太多,需要另行审批");
}
}
}
3. 客户端(Client 角色)
public class LeaveRequestClient {
public static void main(String[] args) {
// 构建责任链:组长 -> 经理 -> 总监
Approver teamLeader = new TeamLeader();
Approver manager = new Manager();
Approver director = new Director();
teamLeader.setNext(manager);
manager.setNext(director);
// 发起请假请求
System.out.println("员工请假 0.5 天:");
teamLeader.handleRequest(0);
System.out.println("\n员工请假 2 天:");
teamLeader.handleRequest(2);
System.out.println("\n员工请假 5 天:");
teamLeader.handleRequest(5);
System.out.println("\n员工请假 10 天:");
teamLeader.handleRequest(10);
}
}
💡 类与角色对照表
类名 | 模式角色 | 说明 |
| Handler | 抽象处理者,定义处理接口和链的引用 |
| ConcreteHandler | 组长,负责审批 ≤1 天的请假 |
| ConcreteHandler | 经理,负责审批 ≤3 天的请假 |
| ConcreteHandler | 总监,负责审批 ≤7 天的请假 |
| Client | 创建链条并发起请求 |
六、优缺点分析
✅ 优点
- 解耦请求与处理者:请求发送者无需知道具体哪个处理类负责;
- 符合开闭原则:新增处理器无需修改现有代码,只需添加新节点;
- 链式组合灵活:可按需调整处理顺序、组合链条结构;
- 请求可被多个处理器处理:一旦处理完就可终止传递,也可继续传递。
❌ 缺点
- 链太长影响性能:每个请求都要沿链查找,节点多时性能下降;
- 调试困难:请求处理的过程不容易追踪;
- 处理者可能被遗漏:若链尾未处理请求,容易造成无响应(需兜底)。
七、责任链模式常见应用
应用场景 | 描述 |
Java Servlet 过滤器 | 多个过滤器按顺序处理 HTTP 请求 |
Spring Security 过滤链 | 登录认证、权限验证、拦截器等依次处理 |
日志处理链 | 多级日志记录器,控制台/文件/远程日志等 |
审批流程引擎 | 审批人链式传递 |
数据校验链 | 参数合法性校验、格式验证等串联处理 |
八、总结(Summary)
责任链模式通过链式结构组织多个处理对象,实现请求处理的灵活分发与扩展,是一种强大且常见的行为型设计模式。它使得系统具备高度可扩展性,特别适合用在审批流、过滤链、日志系统等连续责任分发场景中。