# 什么是责任链模式?一般用在什么场景?
9 min read
Table of Contents
什么是责任链模式?一般用在什么场景?
责任链模式面试标准答案
【核心定义】
责任链模式是一种行为设计模式,它允许将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求为止,实现了请求发送者与接收者的解耦。
【关键要点】
- 核心结构:由抽象处理者(Handler)、具体处理者(ConcreteHandler)和客户端(Client)组成,处理者之间通过引用形成链式结构
- 处理流程:请求从链的一端进入,依次经过每个处理者判断,符合条件则处理,否则传递给下一个
- 灵活性:可以动态调整处理链的顺序和组成,新增处理者无需修改现有代码
- 终止机制:必须明确定义请求被处理的终止条件,避免无限传递
【深度推导/细节】
核心矛盾与解决方案
矛盾:如何让多个对象都有机会处理请求,同时避免请求发送者与接收者的紧耦合?
逻辑拆解:
- Step 1:定义统一的处理接口,所有处理者实现相同的处理方法
- Step 2:每个处理者持有对下一个处理者的引用,形成链式结构
- Step 3:客户端只需将请求发送给链的第一个处理者,无需知道具体由谁处理
- Step 4:处理者判断自己能否处理,能则处理并终止,不能则传递给下一个
- Step 5:链的末端通常设置默认处理者或空处理,确保所有请求都有归宿
关键设计考量
- 链的构建方式:可以在代码中硬编码,也可以通过配置文件动态构建
- 性能优化:对于长责任链,可考虑引入缓存机制,记录每个请求类型的最佳处理者
- 异常处理:需要定义当所有处理者都无法处理时的兜底策略
【关联/对比】
与其他模式的区别
-
与装饰器模式对比
- 责任链:多个处理者依次尝试处理同一个请求,通常只有一个处理者真正处理
- 装饰器:多个装饰器依次处理请求,每个装饰器都会对请求进行增强处理
-
与状态模式对比
- 责任链:处理者之间是独立的,不知道彼此的存在
- 状态模式:状态之间相互知晓,可以主动切换到下一个状态
-
与命令模式结合
- 责任链常与命令模式结合,将命令对象作为请求在责任链中传递
【典型应用场景】
1. 请求处理流程
- Web框架的过滤器链:如Servlet Filter,每个Filter处理请求后决定是否传递给下一个
- 审批流程系统:不同级别的领导审批,金额越大需要的审批级别越高
- 日志记录系统:不同级别的日志(DEBUG、INFO、ERROR)由不同的处理器处理
2. 事件处理机制
- GUI事件处理:如Java AWT/Swing中的事件传播
- 异常处理:try-catch-finally本质上是一种责任链
- 中间件拦截器:如Spring Interceptor链
3. 具体技术实现
- Java Servlet Filter:最经典的责任链实现
- Spring Security过滤器链:多个安全过滤器依次检查
- Netty的ChannelHandler链:处理网络IO事件
- MyBatis的插件机制:通过InterceptorChain实现
【实现要点与最佳实践】
纯责任链 vs 不纯责任链
- 纯责任链:请求必须被某个处理者处理,且只能被一个处理者处理
- 不纯责任链:请求可以被多个处理者处理,或可能不被任何处理者处理
链的构建方式
// 方式1:客户端显式构建Handler chain = new ConcreteHandlerA( new ConcreteHandlerB( new ConcreteHandlerC(null)));
// 方式2:通过工厂或配置构建HandlerChainBuilder builder = new HandlerChainBuilder();builder.addHandler(new A()).addHandler(new B()).build();性能考虑
- 对于长责任链,可引入短路机制:一旦找到合适处理者立即返回
- 考虑使用责任链+策略模式:根据请求类型选择不同的处理链
『面试官追问』
-
责任链模式的优缺点是什么?
- 优点:降低耦合度、增强灵活性、符合开闭原则
- 缺点:请求可能未被处理、性能问题(长链)、调试困难
-
如何处理责任链中的循环引用问题?
- 在构建链时检测环,使用visited集合记录已添加的处理者
- 设置最大传递次数限制,防止无限循环
-
责任链模式与中间件模式的关系?
- 中间件模式是责任链模式的特化应用,通常用于处理请求/响应管道
- 中间件通常允许请求和响应双向处理,而责任链更多是单向
-
如何实现可动态调整的责任链?
- 使用链表或列表存储处理者,支持动态增删
- 结合观察者模式,当链变化时通知相关组件
-
在微服务架构中责任链模式的应用?
- API网关的过滤器链
- 分布式追踪的上下文传递
- 服务调用的重试和熔断链
【实际案例演示】
Spring Security过滤器链示例
// 简化的责任链实现public class SecurityFilterChain { private List<Filter> filters = new ArrayList<>();
public void doFilter(HttpServletRequest request, HttpServletResponse response) { FilterChain chain = new VirtualFilterChain(filters); chain.doFilter(request, response); }
private static class VirtualFilterChain implements FilterChain { private Iterator<Filter> iterator;
public VirtualFilterChain(List<Filter> filters) { this.iterator = filters.iterator(); }
@Override public void doFilter(HttpServletRequest request, HttpServletResponse response) { if (iterator.hasNext()) { Filter nextFilter = iterator.next(); nextFilter.doFilter(request, response, this); } // 链结束,请求继续向下传递 } }}审批系统示例
// 抽象处理者public abstract class Approver { protected Approver nextApprover; protected String name;
public void setNext(Approver approver) { this.nextApprover = approver; }
public abstract void processRequest(PurchaseRequest request);}
// 具体处理者:经理public class Manager extends Approver { @Override public void processRequest(PurchaseRequest request) { if (request.getAmount() <= 5000) { System.out.println(name + "审批采购单:" + request); } else if (nextApprover != null) { nextApprover.processRequest(request); } }}【总结】
责任链模式通过构建处理者链实现了请求处理逻辑的灵活组织和动态配置,特别适用于需要多个对象按顺序处理请求的场景。在实际应用中,需要注意链的终止条件、性能优化和动态调整能力,避免出现请求未被处理或性能瓶颈的问题。该模式在Web框架、审批流程、事件处理等场景有广泛应用,是解耦请求发送者和接收者的有效手段。