1. 责任链模式初探:从现实场景到代码实现
第一次接触责任链模式是在处理一个电商平台的订单审批系统时。当时的需求是:不同金额的订单需要经过不同级别主管审批,50万以下由部门经理处理,50-100万需要总监过目,超过100万则必须CEO签字。最初我写了这样一堆if-else:
if (order.getAmount() < 500000) { departmentManager.approve(order); } else if (order.getAmount() < 1000000) { director.approve(order); } else { ceo.approve(order); }直到我的技术主管拍着我的肩膀说:"小伙子,知道责任链模式吗?你这代码三个月后肯定要重写。"后来我才明白,当审批层级增加或审批规则变化时,这种硬编码方式简直就是维护噩梦。
责任链模式(Chain of Responsibility Pattern)的核心思想是:让多个对象都有机会处理请求,从而避免请求发送者与接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有对象处理它为止。
关键理解:责任链不是"if-else的替代品",而是"动态可配置的处理流水线"。就像快递配送网络,包裹会自动路由到能处理它的站点,而不是固定走死路线。
2. 责任链模式的骨骼解剖
2.1 标准UML结构与角色定义
先来看经典的责任链模式类图(以审批流程为例):
┌─────────────┐ ┌──────────────────┐ │ Handler │<----│ ConcreteHandler │ ├─────────────┤ ├──────────────────┤ │+setNext() │ │+handleRequest() │ │+handleRequest()│ └──────────────────┘ └─────────────┘ ^ | ┌──────────────────┐ │ Client │ └──────────────────┘各角色职责:
- Handler(抽象处理者):定义处理请求的接口,通常包含设置下一个处理者的方法和处理请求的抽象方法
- ConcreteHandler(具体处理者):实现具体的处理逻辑,能处理则处理,否则转给下一个
- Client(客户端):创建处理链,并向链头的处理者提交请求
2.2 模式变体与实现方式
实际开发中常见几种实现形态:
形态一:纯手工链(基础版)
public abstract class Handler { protected Handler next; public Handler setNext(Handler next) { this.next = next; return next; // 返回next便于链式调用 } public abstract void handle(Request request); }形态二:拦截器链(带中断机制)
public interface Interceptor { boolean intercept(Request request); } // 使用时 for (Interceptor interceptor : chain) { if (interceptor.intercept(request)) { break; // 任一拦截器返回true则终止传递 } }形态三:过滤器链(全链路执行)
public interface Filter { void doFilter(Request request, Response response, FilterChain chain); } // 典型实现 public void doFilter(Request req, Response res, FilterChain chain) { // 前置处理 chain.doFilter(req, res); // 传递给下一个过滤器 // 后置处理 }实战经验:Spring MVC的拦截器链、Servlet的Filter链都是责任链的变体实现。理解这个模式后,看这些框架源码会豁然开朗。
3. 深度实现:从玩具代码到生产级实现
3.1 基础实现示例
以员工请假审批为例,先看最简实现:
// 抽象处理者 public abstract class Approver { protected Approver nextApprover; public void setNext(Approver next) { this.nextApprover = next; } public abstract void processLeave(LeaveRequest request); } // 具体处理者:项目经理 public class ProjectManager extends Approver { @Override public void processLeave(LeaveRequest request) { if (request.getDays() <= 3) { System.out.println("项目经理批准" + request.getName() + "请假" + request.getDays() + "天"); } else if (nextApprover != null) { nextApprover.processLeave(request); } } } // 具体处理者:部门经理 public class DeptManager extends Approver { @Override public void processLeave(LeaveRequest request) { if (request.getDays() <= 7) { System.out.println("部门经理批准" + request.getName() + "请假" + request.getDays() + "天"); } else if (nextApprover != null) { nextApprover.processLeave(request); } } } // 使用示例 public class Client { public static void main(String[] args) { Approver pm = new ProjectManager(); Approver dm = new DeptManager(); pm.setNext(dm); pm.processLeave(new LeaveRequest("张三", 2)); pm.processLeave(new LeaveRequest("李四", 5)); pm.processLeave(new LeaveRequest("王五", 9)); } }3.2 生产环境优化方案
实际项目中的增强点:
1. 链式构建优化
// 建造者风格链式构造 public class HandlerChain { private Handler head; private Handler tail; public HandlerChain addHandler(Handler handler) { if (head == null) { head = tail = handler; } else { tail.setNext(handler); tail = handler; } return this; } public void handle(Request request) { if (head != null) { head.handle(request); } } } // 使用方式 new HandlerChain() .addHandler(new HandlerA()) .addHandler(new HandlerB()) .handle(request);2. 异步责任链实现
public class AsyncHandler implements Handler { private final Executor executor; private Handler next; public AsyncHandler(Executor executor) { this.executor = executor; } @Override public void handle(Request request) { executor.execute(() -> { if (canHandle(request)) { // 处理逻辑 } else if (next != null) { next.handle(request); } }); } }3. 链路监控与诊断
public abstract class MonitorableHandler implements Handler { private static final ThreadLocal<LinkedList<String>> trace = ThreadLocal.withInitial(LinkedList::new); @Override public final void handle(Request request) { trace.get().add(getClass().getSimpleName()); try { doHandle(request); } finally { trace.get().removeLast(); } } protected abstract void doHandle(Request request); public static String getCurrentTrace() { return String.join("->", trace.get()); } }避坑指南:生产环境中要特别注意链路的循环引用检测,可以通过在Handler中加入
visited标记或在构建链时做环路检测。
4. 实战对比:责任链模式VS其他模式
4.1 与状态模式的异同
相似点:
- 都有状态/责任转移的概念
- 都能避免大量的条件判断
本质区别:
- 状态模式:状态转移由当前状态决定(自我管理)
- 责任链:请求传递由处理者决定(外部管理)
示例场景差异:
- 订单状态流转(状态模式更合适)
- 权限校验链条(责任链更合适)
4.2 与装饰器模式的对比
这对"孪生兄弟"经常让人混淆:
| 维度 | 责任链模式 | 装饰器模式 |
|---|---|---|
| 目的 | 分散处理,可能提前终止 | 层层增强,全部执行 |
| 对象关系 | 处理者彼此独立 | 装饰器依赖被装饰对象 |
| 典型应用 | 审批流程、过滤器链 | IO流、Wrapper类 |
| 控制流向 | 单向传递 | 双向嵌套 |
4.3 与策略模式组合使用
二者结合能产生强大威力:
// 策略接口 public interface ValidationStrategy { boolean validate(User user); } // 策略实现 public class AgeValidation implements ValidationStrategy { public boolean validate(User user) { return user.getAge() >= 18; } } // 责任链处理者 public class ValidationHandler implements Handler { private List<ValidationStrategy> strategies; public ValidationHandler(List<ValidationStrategy> strategies) { this.strategies = strategies; } public void handle(Request request) { for (ValidationStrategy strategy : strategies) { if (!strategy.validate(request.getUser())) { throw new ValidationException(strategy.getClass().getSimpleName() + " failed"); } } // 传递给下一个handler } }这种组合既保持了策略的灵活性,又获得了责任链的可扩展性。
5. 真实框架中的责任链模式剖析
5.1 Spring拦截器链实现
Spring MVC的拦截器是责任链的经典案例:
public class DispatcherServlet extends FrameworkServlet { protected void doDispatch(HttpServletRequest request, HttpServletResponse response) { HandlerExecutionChain mappedHandler = getHandler(request); // 前置处理 if (!mappedHandler.applyPreHandle(request, response)) { return; // 拦截器返回false则中断 } // 实际处理器调用 ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler()); // 后置处理 mappedHandler.applyPostHandle(request, response, mv); } } // HandlerExecutionChain关键代码 public class HandlerExecutionChain { private final List<HandlerInterceptor> interceptorList = new ArrayList<>(); boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) { for (HandlerInterceptor interceptor : interceptorList) { if (!interceptor.preHandle(request, response, this.handler)) { return false; } } return true; } }5.2 Netty的ChannelPipeline
Netty的Pipeline是责任链的另一种精彩实现:
public class DefaultChannelPipeline implements ChannelPipeline { final AbstractChannelHandlerContext head; final AbstractChannelHandlerContext tail; public ChannelPipeline addLast(String name, ChannelHandler handler) { AbstractChannelHandlerContext newCtx = newContext(group, name, handler); addLast0(newCtx); return this; } private void addLast0(AbstractChannelHandlerContext newCtx) { AbstractChannelHandlerContext prev = tail.prev; newCtx.prev = prev; newCtx.next = tail; prev.next = newCtx; tail.prev = newCtx; } }每个ChannelHandler处理完事件后,会调用ctx.fireXXX()方法将事件传递给下一个Handler。
5.3 MyBatis插件机制
MyBatis的插件系统也是基于责任链:
public class Plugin implements InvocationHandler { public static Object wrap(Object target, Interceptor interceptor) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new Plugin(target, interceptor)); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (interceptor.getClass().isAssignableFrom(Interceptor.class)) { return interceptor.intercept(new Invocation(target, method, args)); } return method.invoke(target, args); } } // 实际使用 @Intercepts(@Signature(type= Executor.class, method="update", args={MappedStatement.class,Object.class})) public class ExamplePlugin implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { // 前置处理 Object result = invocation.proceed(); // 调用责任链下一个 // 后置处理 return result; } }6. 复杂场景下的模式变体
6.1 分支型责任链
某些场景需要根据条件走不同处理链:
public class RouterHandler implements Handler { private Map<Predicate<Request>, Handler> routeRules = new HashMap<>(); public RouterHandler addRoute(Predicate<Request> predicate, Handler handler) { routeRules.put(predicate, handler); return this; } @Override public void handle(Request request) { routeRules.entrySet().stream() .filter(entry -> entry.getKey().test(request)) .findFirst() .ifPresent(entry -> entry.getValue().handle(request)); } }6.2 双向责任链
Zookeeper的Watcher机制就是双向传递的典型案例:
public class BidirectionalHandler implements Handler { private Handler next; private Handler prev; @Override public void handle(Request request) { // 向前传递 if (prev != null && request.needPropagateBack()) { prev.handle(request); } // 自身处理 doHandle(request); // 向后传递 if (next != null && request.needPropagateForward()) { next.handle(request); } } }6.3 可回溯责任链
需要支持"撤回"操作时的设计:
public class UndoableHandler implements Handler { private final Deque<Command> commandStack = new ArrayDeque<>(); @Override public void handle(Request request) { Command command = createCommand(request); try { command.execute(); commandStack.push(command); if (next != null) next.handle(request); } catch (Exception e) { while (!commandStack.isEmpty()) { commandStack.pop().undo(); } } } }7. 性能优化与常见陷阱
7.1 责任链的性能坑
问题场景:
- 链条过长(超过10个handler)
- 每个handler都有耗时操作
- 高频调用场景
优化方案:
- 异步化处理(如Netty的EventLoop)
- 热点handler前置
- 缓存判断结果
- 并行执行无依赖的handler
// 并行责任链示例 public class ParallelHandler implements Handler { private List<Handler> handlers; public void handle(Request request) { List<CompletableFuture<Void>> futures = handlers.stream() .map(handler -> CompletableFuture.runAsync(() -> handler.handle(request))) .collect(Collectors.toList()); CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); } }7.2 典型反模式
1. 循环引用陷阱
Handler h1 = new ConcreteHandler(); Handler h2 = new ConcreteHandler(); h1.setNext(h2); h2.setNext(h1); // 循环引用!2. 责任逃逸问题
public void handle(Request request) { if (canHandle(request)) { // 处理但忘记返回 } next.handle(request); // 无论如何都会继续传递 }3. 状态污染
public class StatefulHandler implements Handler { private int count; // 状态变量 public void handle(Request request) { count++; // 处理逻辑 } } // 多线程环境下会出现竞态条件7.3 调试技巧
1. 链路追踪
public abstract class TraceableHandler implements Handler { public final void handle(Request request) { long start = System.nanoTime(); MDC.put("handler", getClass().getSimpleName()); try { doHandle(request); } finally { long duration = System.nanoTime() - start; log.info("Handler {} took {} ns", getClass().getSimpleName(), duration); MDC.remove("handler"); } } }2. 可视化工具使用Arthas等工具跟踪调用链:
watch com.example.Handler handle '{params, target, returnObj}' -x 38. 测试策略与最佳实践
8.1 单元测试方案
测试单个Handler
@Test void testSingleHandler() { TestHandler handler = new TestHandler(); handler.setNext(null); // 隔离测试 Request request = new Request(); handler.handle(request); assertTrue(request.isHandled()); assertEquals(handler, request.getHandler()); }测试完整链条
@Test void testFullChain() { Handler chain = createChain(); Request request = new Request(Level.MEDIUM); chain.handle(request); assertNotNull(request.getHandler()); assertEquals(MediumHandler.class, request.getHandler().getClass()); }8.2 集成测试要点
- 链条完整性验证:
@Test void testChainIntegrity() { Handler head = createProductionChain(); int count = 0; Handler current = head; while (current != null) { count++; current = ((AbstractHandler)current).getNext(); } assertEquals(5, count); // 预期5个handler }- 性能基准测试:
@Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MICROSECONDS) public void testChainPerformance(Blackhole bh) { Handler chain = createBenchmarkChain(); Request request = new Request(); chain.handle(request); bh.consume(request); }8.3 设计原则与取舍
适用场景:
- 多个对象可以处理同一请求,但具体由谁处理在运行时动态确定
- 需要在不明确指定接收者的情况下向多个对象中的一个提交请求
- 可动态指定处理者集合或顺序
不适用情况:
- 请求有明确的唯一处理者
- 请求必须被某个特定对象处理
- 处理流程是静态不变的
黄金法则:
- 保持处理者的单一职责
- 避免链条过长(超过10个应考虑分治)
- 优先使用不可变处理者
- 明确处理结果的契约(是否被处理、是否继续传递)
9. 现代演进:响应式责任链
随着Reactive编程兴起,责任链也有了新形态:
public class ReactiveHandler { private final List<Handler> handlers; public Mono<Void> handle(ServerWebExchange exchange) { return Flux.fromIterable(handlers) .concatMap(handler -> handler.handle(exchange)) .then(); } } // 使用示例 @Bean public ReactiveHandler reactiveChain() { return new ReactiveHandler(List.of( new LoggingHandler(), new AuthHandler(), new BusinessHandler() )); }这种模式特别适合高并发的非阻塞场景,如Spring WebFlux。
10. 从设计模式到领域模式
在DDD中,责任链可以升华为领域模式:
public class OrderProcessingPipeline { private final List<OrderProcessor> processors; public Order process(Order order) { Order current = order; for (OrderProcessor processor : processors) { current = processor.process(current); if (current.isTerminated()) { break; } } return current; } } // 领域处理器 public interface OrderProcessor { Order process(Order order); } // 具体实现 public class InventoryCheckProcessor implements OrderProcessor { public Order process(Order order) { if (!inventoryService.check(order.getItems())) { return order.markAsFailed("库存不足"); } return order; } }这种模式将技术实现与业务语义完美结合,是责任链的高级应用形态。