🎯 一、模式概述
1.1 什么是责任链模式?
责任链模式(Chain of Responsibility Pattern) 是一种行为型设计模式,它允许多个对象都有机会处理同一个请求,从而避免请求的发送者与接收者之间的耦合关系。这些处理对象被连成一条链,并沿着这条链传递请求,直到有对象处理它为止。
1.2 模式目的
- 解耦请求发送者与接收者:发送者无需知道哪个对象会处理请求。
- 动态构建处理流程:可以在运行时决定由哪些对象来处理请求,以及它们的顺序。
- 增强灵活性与可扩展性:新增处理逻辑时无需修改已有代码,符合开闭原则。
1.3 模式类型
| 分类 | 类型 |
|---|---|
| 设计模式分类 | 行为型模式(Behavioral Pattern) |
🧩 二、模式结构
责任链模式由以下主要角色组成:
2.1 角色说明
| 角色 | 说明 |
|---|---|
| Handler(抽象处理者) | 定义处理请求的接口,通常包含一个处理方法(如 handle() / process()),以及一个指向下一个处理者的引用(next / successor)。 |
| ConcreteHandler(具体处理者) | 实现抽象处理者接口,处理它所负责的请求;如果不能处理,则将请求传递给链中的下一个处理者。 |
| Client(客户端) | 创建处理者链,并向链上的第一个处理者提交请求。 |
2.2 类图(UML 结构)
+----------------+ +---------------------+ +---------------------+
| Client |------>| Handler |<------| ConcreteHandler |
+----------------+ +---------------------+ +---------------------+
| | | +setNextHandler() | | +processRequest() |
| +trigger() | | +processRequest() | | (具体处理逻辑) |
+----------------+ +----------+----------+ +----------+----------+
^
|
+----------+----------+
| ConcreteHandler2 |
+---------------------+
| +processRequest() |
+---------------------+
🖼 Client 调用 Handler 链,Handler 是抽象类,下面有若干具体实现(如 ConcreteHandler1/2/3),每个 Handler 持有一个对下一个 Handler 的引用(nextHandler)。
💼 三、适用场景
责任链模式适用于以下场景:
| 场景 | 说明 |
|---|---|
| 多对象可选处理请求 | 请求可由多个对象中的一个处理,但具体由谁处理在运行时决定 |
| 审批流程 | 如请假、报销等逐级审批,不同级别处理不同范围 |
| 过滤器 / 拦截器 | 如 Web 中的 Filter、Spring Security 过滤器链 |
| 日志分级处理 | 不同级别日志由不同 Handler 处理 |
| 异常处理机制 | 按异常类型逐级上报或处理 |
| 中间件 / 流程管道 | 如 Netty 的 ChannelPipeline、任务处理流水线 |
🛠 四、示例:请假审批流程
4.1 需求背景
员工请假审批规则如下:
- 小于等于 3 天,组长审批
- 4 ~ 7 天,经理审批
- 8 ~ 15 天,总监审批
- 超过 15 天,拒绝
- 后续可扩展如 HR 备案等环节
4.2 传统实现方式的问题(if-else)
public class LeaveService {
public boolean approve(int days) {
if(days <= 3) {
return GroupLeader.approve();
} else if(days <= 7) {
return Manager.approve();
} else if(days <= 15) {
return Director.approve();
} else {
System.out.println("请假天数过长,拒绝审批");
return false;
}
}
}
❌ 缺点:
- 所有逻辑集中在一个方法中,难以维护;
- 增加新角色(如 HR)必须修改原代码;
- 违反开闭原则;
- 审批流程不灵活,难以动态调整。
4.3 责任链模式改造
4.3.1 抽象处理者(Handler)
// 抽象处理者
public abstract class Approver {
protected Approver nextApprover;
// 设置下一个处理者,支持链式调用
public Approver setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
return nextApprover;
}
// 处理请求的抽象方法
public abstract void processRequest(int days);
}
4.3.2 具体处理者(ConcreteHandler)
// 组长
public class TeamLeader extends Approver {
@Override
public void processRequest(int days) {
if (days <= 3) {
System.out.println("组长批准了 " + days + " 天的请假");
} else if (nextApprover != null) {
nextApprover.processRequest(days);
} else {
System.out.println("异常:未设置后续审批人!");
}
}
}
// 经理
public class Manager extends Approver {
@Override
public void processRequest(int days) {
if (days > 3 && days <= 7) {
System.out.println("经理批准了 " + days + " 天的请假");
} else if (nextApprover != null) {
nextApprover.processRequest(days);
} else {
System.out.println("异常:未设置后续审批人!");
}
}
}
// 总监
public class Director extends Approver {
@Override
public void processRequest(int days) {
if (days > 7 && days <= 15) {
System.out.println("总监批准了 " + days + " 天的请假");
} else if (days > 15) {
System.out.println("驳回大于15天的假期请求!");
} else if (nextApprover != null) {
nextApprover.processRequest(days);
}
}
}
链终止控制:组长和经理处理器中保留nextApprover != null判断,防止空指针;总监处理器作为终审节点,不再传递请求。
业务属性扩展:days可以封装为请求对象,扩展更多业务属性。
4.3.3 责任链组装(ChainBuilder)
public class ChainBuilder {
public static Approver buildChain() {
Approver teamLeader = new TeamLeader();
Approver manager = new Manager();
Approver director = new Director();
return teamLeader
.setNextApprover(manager)
.setNextApprover(director);
}
}
可以增加空值校验,比如
Approver teamLeader = new TeamLeader();
if(teamLeader == null)
throw new IllegalArgumentException();
Approver manager = new Manager();
if(manager == null)
throw new IllegalArgumentException();
Approver director = new Director();
if(director == null)
throw new IllegalArgumentException();
4.3.4 客户端调用
public class Client {
public static void main(String[] args) {
Approver chain = ChainBuilder.buildChain();
System.out.println("=== 请假2天 ===");
chain.processRequest(2);
System.out.println("\n=== 请假5天 ===");
chain.processRequest(5);
System.out.println("\n=== 请假10天 ===");
chain.processRequest(10);
System.out.println("\n=== 请假20天 ===");
chain.processRequest(20);
}
}
✅ 输出结果:
=== 请假2天 ===
组长批准了 2 天的请假
=== 请假5天 ===
经理批准了 5 天的请假
=== 请假10天 ===
总监批准了 10 天的请假
=== 请假20天 ===
驳回大于15天的假期请求!
4.4 扩展示例:增加 HR 备案
// HR备案处理器
public class HrRecorder extends Approver {
@Override
public void processRequest(int days) {
System.out.println("HR备案 [" + days + "] 天请假记录");
// 备案后不继续传递
}
}
更新 ChainBuilder:
public class ChainBuilder {
public static Approver buildChain() {
Approver teamLeader = new TeamLeader();
Approver manager = new Manager();
Approver director = new Director();
Approver hr = new HrRecorder();
return teamLeader
.setNextApprover(manager)
.setNextApprover(director)
.setNextApprover(hr);
}
}
4.5 可能遇到的问题
-
循环链 表象:A->B->A形成死循环。 解决:在setNextApprover方法中增加环路检测。
public Approver setNextApprover(Approver nextApprover) { if (isInChain(nextApprover)) throw new IllegalArgumentException("环路检测未通过!"); this.nextApprover = nextApprover; return nextApprover; } -
请求丢失 表象:所有处理器都不处理请求 解决:添加默认处理器作为链尾
public class DefaultHandler extends Approver { @Override public void process(LeaveRequest request) { System.out.println("请求未被任何处理器处理!"); } } -
顺序敏感 表象:先添加经理再添加组长 解决:使用建造者模式封装链条构建 public class ChainBuilder { private List handlers = new ArrayList<>();
public ChainBuilder addHandler(Approver handler) { handlers.add(handler); return this; } public Approver build() { for(int i = 0; i< handlers.size() - 1;i++){ handlers.get(i).setNextApprover(handlers.get(i+1)); } return handlers.get(0); } }
✅ 五、责任链模式的优点
| 优点 | 说明 |
|---|---|
| 低耦合 | 发送者无需知道具体由谁处理请求 |
| 高扩展性 | 可动态添加/移除/重排序处理者 |
| 单一职责 | 每个处理者只关注自己的逻辑 |
| 开闭原则 | 新增处理逻辑无需修改已有代码 |
⚠️ 六、责任链模式的缺点
| 缺点 | 说明 |
|---|---|
| 请求可能未被处理 | 如果链配置不正确,请求可能到达链尾都未被处理 |
| 调试复杂 | 请求传递过程不直观,排查问题需跟踪整个链条 |
| 性能影响 | 请求可能经过多个处理者,链过长时影响性能 |
🧩 七、Java 中的常见应用场景
| 场景 | 说明 |
|---|---|
| Servlet Filter | 请求/响应经过一组过滤器链 |
| Spring Security | 多个安全过滤器组成责任链进行拦截处理 |
| 日志系统 | 不同级别日志由不同处理器处理 |
| 异常处理机制 | 按异常类型逐层上报或处理 |
| 中间件/拦截器 | 如 Netty 的 ChannelPipeline |
📋 八、总结
| 项目 | 说明 |
|---|---|
| 模式名称 | 责任链模式(Chain of Responsibility Pattern) |
| 类型 | 行为型设计模式 |
| 目的 | 解耦请求发送者与接收者,让多个对象都有机会处理请求 |
| 核心机制 | 请求沿处理者链传递,直到被处理或到达链尾 |
| 优点 | 灵活、解耦、可扩展、符合开闭原则 |
| 缺点 | 可能请求未被处理、调试困难、性能问题 |
| 应用 | 审批流程、过滤器、日志系统、异常处理等 |
📎 九、附录:UML 类图
🖼 Client 调用抽象 Approver,其下有 TeamLeader、Manager、Director、HrRecorder 等具体处理者,每个处理者持有一个指向下一个处理者的引用。