责任链模式(Chain of Responsibility Pattern)
责任链模式是一种行为型设计模式,其核心思想是将请求的发送者与接收者解耦,通过构建一条 “接收者链”,让请求在链上传递,直到有一个接收者能够处理该请求为止。这种模式避免了请求发送者与具体处理者之间的直接依赖,增强了系统的灵活性和可扩展性。
一、定义
官方定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
通俗理解:类比生活中的 “审批流程”(如报销审批:员工→部门经理→财务总监→CEO),报销单(请求)会从链的起点开始传递,每个审批人(处理者)判断自己是否有权限处理,有权限则处理,无权限则传递给下一个审批人,直到请求被处理或链结束。
二、意图
- 解耦请求发送者与处理者:发送者无需知道请求由哪个处理者处理,只需将请求提交到链上即可。
- 动态组合处理流程:可通过动态调整链中处理者的顺序或增减处理者,灵活修改请求的处理逻辑。
- 避免请求发送者与多个处理者的直接关联:减少类之间的依赖,降低系统复杂度。
三、结构
责任链模式的核心结构包含4 个角色,各角色职责明确,协同完成请求的传递与处理:
| 角色名称 | 核心职责 |
|---|---|
| 抽象处理者(Handler) | 定义处理请求的接口(如 handleRequest() 方法),并维护一个 “下一个处理者” 的引用。 |
| 具体处理者(ConcreteHandler) | 实现抽象处理者的接口,判断自身是否能处理请求: - 能处理:直接处理请求; - 不能处理:将请求传递给 “下一个处理者”。 |
| 请求对象(Request) | 封装请求的相关信息(如请求类型、请求内容、请求优先级等),供处理者判断是否处理。 |
| 客户端(Client) | 创建具体处理者对象,构建责任链,并将请求提交到链的起点(第一个处理者)。 |
四、优点
- 解耦发送者与处理者:发送者无需知道请求的具体处理者,处理者也无需知道发送者,两者通过链间接通信。
- 灵活性高:可动态调整链中处理者的顺序、增减处理者,无需修改原有代码(符合开闭原则)。
- 单一职责:每个具体处理者只需关注自身职责范围内的请求处理,逻辑清晰,便于维护。
- 简化客户端代码:客户端只需将请求提交到链的起点,无需关心后续处理流程。
五、缺点
- 请求可能 “丢失”:若链中所有处理者都无法处理请求,且未设置 “默认处理者”,请求会被丢弃,可能导致业务异常。
- 性能开销:请求需从链的起点依次传递到处理者,若链过长,会增加请求处理的延迟。
- 调试复杂度高:请求的处理路径分散在多个处理者中,问题排查时需跟踪整个链的传递过程。
六、类图(Mermaid)

classDiagram
direction TB
class Handler {
+Handler nextHandler
+setNextHandler(Handler): void
+abstract handleRequest(Request): void
}
class ConcreteHandlerA {
+handleRequest(Request): void
}
class ConcreteHandlerB {
+handleRequest(Request): void
}
class ConcreteHandlerC {
+handleRequest(Request): void
}
class Request {
-requestType: String
-requestContent: String
-priority: int
+getRequestType(): String
+getRequestContent(): String
+getPriority(): int
}
class Client {
+main(): void
}
Handler <|-- ConcreteHandlerA
Handler <|-- ConcreteHandlerB
Handler <|-- ConcreteHandlerC
Handler "1" --> "0..1" Handler : has next
Client --> Handler : creates & builds chain
Client --> Request : creates
Handler --> Request : processes
七、时序图(Mermaid)
以 “报销审批” 为例,时序图展示请求(报销单)在链中传递的过程:
sequenceDiagram
participant Client
participant EmpHandler as 员工(链起点)
participant MgrHandler as 部门经理
participant FinHandler as 财务总监(链终点)
participant Request as 报销单(请求)
%% 1. 客户端创建请求和处理者,构建责任链
Client->>Request: 创建报销单(金额5000元)
Client->>EmpHandler: 创建员工处理者
Client->>MgrHandler: 创建部门经理处理者
Client->>FinHandler: 创建财务总监处理者
Client->>EmpHandler: 设置下一个处理者(部门经理)
Client->>MgrHandler: 设置下一个处理者(财务总监)
%% 2. 客户端提交请求到链起点
Client->>EmpHandler: 提交报销请求
EmpHandler->>EmpHandler: 判断:无审批权限(仅发起)
EmpHandler->>MgrHandler: 传递请求(报销5000元)
%% 3. 部门经理处理请求
MgrHandler->>MgrHandler: 判断:权限≤3000元,5000元超权限
MgrHandler->>FinHandler: 传递请求(报销5000元)
%% 4. 财务总监处理请求
FinHandler->>FinHandler: 判断:权限≤10000元,5000元符合权限
FinHandler->>Client: 反馈:报销审批通过
八、适用环境
当系统满足以下场景时,适合使用责任链模式:
- 有多个对象可能处理同一个请求,但具体处理者需在运行时确定(如审批流程、日志级别处理)。
- 需动态指定请求的处理流程(如可配置的过滤链、拦截器链)。
- 请求发送者不希望与具体处理者耦合(如框架设计中,用户无需关心内部处理逻辑)。
- 需避免请求发送者与多个处理者直接关联(如避免大量
if-else或switch判断处理者)。
九、模式分析
- 链的构建方式:
- 客户端构建:客户端明确知道所有处理者,手动组装链(如示例中客户端设置
nextHandler)。 - 处理者自构建:处理者在初始化时自动关联下一个处理者(减少客户端依赖,但灵活性降低)。
- 客户端构建:客户端明确知道所有处理者,手动组装链(如示例中客户端设置
- 请求的传递逻辑:
- 单向传递:请求从链的起点到终点,仅沿一个方向传递(最常见)。
- 循环传递:链的终点关联起点,请求循环传递(需避免死循环,适用于特殊场景)。
- 处理者的判断逻辑:
- 排他处理:仅一个处理者处理请求(如审批流程,仅最终审批人处理)。
- 叠加处理:多个处理者依次处理请求(如过滤器链,每个过滤器都处理请求)。
十、模式扩展
责任链模式可根据业务需求进行扩展,常见扩展形式如下:
- 带默认处理者的责任链:在链的终点添加 “默认处理者”,若所有处理者无法处理请求,由默认处理者兜底(避免请求丢失)。
- 可中断的责任链:处理者处理请求后,可选择是否继续传递请求(如叠加处理场景,处理后继续传递;排他处理场景,处理后中断传递)。
- 带优先级的责任链:请求携带优先级,处理者仅处理指定优先级的请求(如日志系统,
ERROR级日志由控制台 + 文件处理,INFO级日志仅由文件处理)。 - 动态调整的责任链:运行时可动态添加 / 移除处理者(如插件化架构,通过插件动态扩展处理逻辑)。
十一、模式应用
责任链模式在框架和业务系统中应用广泛,典型场景包括:
- 框架层面:
- Java Servlet 的
Filter链:请求经过多个过滤器处理(如登录验证、字符编码过滤、权限检查)。 - Spring 的
Interceptor链:Spring MVC 中请求经过多个拦截器处理。 - Netty 的
ChannelPipeline:网络请求经过多个ChannelHandler处理(解码、编码、业务处理)。
- Java Servlet 的
- 业务层面:
- 审批流程:报销审批、请假审批、采购审批等。
- 日志系统:不同级别日志(
DEBUG/INFO/WARN/ERROR)由不同处理器处理。 - 异常处理:不同类型异常(
NullPointerException/IllegalArgumentException)由不同异常处理器处理。 - 订单处理:订单状态流转(待支付→已支付→待发货→已发货→已完成),每个状态由对应处理器处理。
十二、Android 中的应用
在 Android 开发中,责任链模式的典型应用如下:
- 事件分发机制: Android 的 View 事件分发(
dispatchTouchEvent/onInterceptTouchEvent/onTouchEvent)本质是责任链模式:- 链结构:
Activity→PhoneWindow→DecorView→ViewGroup→View。 - 事件传递:触摸事件从
Activity开始向下传递,ViewGroup可拦截事件(onInterceptTouchEvent返回true),若不拦截则传递给子View,直到View处理事件(onTouchEvent返回true)或事件传递到链终点。
- 链结构:
- BroadcastReceiver 有序广播: 有序广播(
sendOrderedBroadcast)按优先级从高到低传递,每个BroadcastReceiver可处理广播,也可通过abortBroadcast()中断广播传递(类似可中断的责任链)。 - OkHttp 的 Interceptor 链: OkHttp 中请求经过多个拦截器处理(如
RetryAndFollowUpInterceptor、BridgeInterceptor、CacheInterceptor、CallServerInterceptor),每个拦截器处理后将请求传递给下一个拦截器,最终完成网络请求。
十三、代码实现(Java 版)
以 “报销审批” 为例,实现责任链模式:
1. 定义请求对象(Request)
封装报销请求的信息(金额、申请人):
// 请求对象:报销单
public class ExpenseRequest {
// 报销金额
private double amount;
// 申请人
private String applicant;
public ExpenseRequest(double amount, String applicant) {
this.amount = amount;
this.applicant = applicant;
}
// Getter 方法
public double getAmount() {
return amount;
}
public String getApplicant() {
return applicant;
}
}
2. 定义抽象处理者(Handler)
定义处理请求的接口,并维护下一个处理者的引用:
// 抽象处理者:审批人
public abstract class Approver {
// 下一个审批人(责任链的下一个节点)
protected Approver nextApprover;
// 设置下一个审批人
public void setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
}
// 抽象方法:处理报销请求(子类需实现)
public abstract void processRequest(ExpenseRequest request);
}
3. 定义具体处理者(ConcreteHandler)
实现不同权限的审批人(部门经理、财务总监、CEO):
// 具体处理者1:部门经理(审批≤3000元)
public class DepartmentManager extends Approver {
@Override
public void processRequest(ExpenseRequest request) {
if (request.getAmount() <= 3000) {
// 部门经理有权限处理,直接审批
System.out.println("部门经理审批通过:" + request.getApplicant() + " 的报销单,金额:" + request.getAmount() + "元");
} else if (nextApprover != null) {
// 无权限,传递给下一个审批人(财务总监)
System.out.println("部门经理无权限审批(金额超3000元),传递给财务总监");
nextApprover.processRequest(request);
} else {
// 无下一个审批人,请求无法处理
System.out.println("部门经理无权限审批,且无后续审批人,请求丢失");
}
}
}
// 具体处理者2:财务总监(审批≤10000元)
public class FinanceDirector extends Approver {
@Override
public void processRequest(ExpenseRequest request) {
if (request.getAmount() <= 10000) {
System.out.println("财务总监审批通过:" + request.getApplicant() + " 的报销单,金额:" + request.getAmount() + "元");
} else if (nextApprover != null) {
System.out.println("财务总监无权限审批(金额超10000元),传递给CEO");
nextApprover.processRequest(request);
} else {
System.out.println("财务总监无权限审批,且无后续审批人,请求丢失");
}
}
}
// 具体处理者3:CEO(审批≤50000元)
public class CEO extends Approver {
@Override
public void processRequest(ExpenseRequest request) {
if (request.getAmount() <= 50000) {
System.out.println("CEO审批通过:" + request.getApplicant() + " 的报销单,金额:" + request.getAmount() + "元");
} else {
// CEO 是链的终点,无权限则直接拒绝
System.out.println("CEO无权限审批(金额超50000元),报销请求拒绝");
}
}
}
4. 客户端(Client)
构建责任链,并提交请求:
// 客户端:组装责任链并测试
public class Client {
public static void main(String[] args) {
// 1. 创建具体处理者
Approver deptMgr = new DepartmentManager();
Approver financeDir = new FinanceDirector();
Approver ceo = new CEO();
// 2. 构建责任链:部门经理 → 财务总监 → CEO
deptMgr.setNextApprover(financeDir);
financeDir.setNextApprover(ceo);
// 3. 提交不同金额的报销请求
System.out.println("=== 测试1:报销2000元 ===");
deptMgr.processRequest(new ExpenseRequest(2000, "张三"));
System.out.println("\n=== 测试2:报销8000元 ===");
deptMgr.processRequest(new ExpenseRequest(8000, "李四"));
System.out.println("\n=== 测试3:报销30000元 ===");
deptMgr.processRequest(new ExpenseRequest(30000, "王五"));
System.out.println("\n=== 测试4:报销60000元 ===");
deptMgr.processRequest(new ExpenseRequest(60000, "赵六"));
}
}
5. 运行结果
=== 测试1:报销2000元 ===
部门经理审批通过:张三 的报销单,金额:2000.0元
=== 测试2:报销8000元 ===
部门经理无权限审批(金额超3000元),传递给财务总监
财务总监审批通过:李四 的报销单,金额:8000.0元
=== 测试3:报销30000元 ===
部门经理无权限审批(金额超3000元),传递给财务总监
财务总监无权限审批(金额超10000元),传递给CEO
CEO审批通过:王五 的报销单,金额:30000.0元
=== 测试4:报销60000元 ===
部门经理无权限审批(金额超3000元),传递给财务总监
财务总监无权限审批(金额超10000元),传递给CEO
CEO无权限审批(金额超50000元),报销请求拒绝
十四、总结
责任链模式通过构建 “处理者链”,实现了请求发送者与接收者的解耦,核心价值在于灵活组织处理流程和减少直接依赖。其优点是灵活性高、职责单一、简化客户端代码;缺点是可能存在请求丢失、性能开销和调试复杂度问题。
在实际开发中,需根据业务场景合理设计链的长度和处理逻辑,避免过度设计(如链过长导致性能问题)。同时,可结合扩展形式(如默认处理者、优先级)优化模式,使其更贴合业务需求。
责任链模式在框架(如 Servlet Filter、OkHttp Interceptor)和业务系统(如审批流程、过滤器)中应用广泛,是解决 “多处理者协同处理请求” 问题的重要设计模式。