1. 责任链模式:告别if-else审批地狱
如果你曾经维护过一个复杂的审批流程系统,肯定对下面这种代码不陌生:
java复制if (request.getAmount() < 1000) {
clerk.approve();
} else if (request.getAmount() < 5000) {
manager.approve();
} else if (request.getAmount() < 10000) {
director.approve();
} else {
ceo.approve();
}
这种代码最可怕的地方在于:每次业务规则变更都需要修改这段核心逻辑。新增审批层级?调整审批金额阈值?不好意思,你得重新测试整个审批流程。这就是典型的"硬编码决策逻辑"问题。
责任链模式(Chain of Responsibility)正是为解决这类问题而生。它像一条流水线,把处理请求的对象连成链条,请求沿着链条传递直到被处理。我在金融系统开发中就曾用这个模式重构过一个贷款审批模块,将原本200多行的if-else缩减为清晰的处理链,后续新增风控环节只需添加新处理器即可。
2. 模式结构与核心组件
2.1 经典责任链结构
标准的责任链模式包含三个关键角色:
-
抽象处理者(Handler)
- 定义处理请求的接口
- 持有下一个处理者的引用(后继者)
- 典型结构:
java复制public abstract class Handler { protected Handler next; public void setNext(Handler next) { this.next = next; } public abstract void handleRequest(Request request); }
-
具体处理者(ConcreteHandler)
- 实现具体的处理逻辑
- 判断自己能否处理,不能则转给后继者
- 示例:
java复制public class ManagerHandler extends Handler { @Override public void handleRequest(Request request) { if (canHandle(request)) { // 处理逻辑 } else if (next != null) { next.handleRequest(request); } } private boolean canHandle(Request request) { // 判断条件 } }
-
客户端(Client)
- 组装处理链
- 发起请求但不关心具体处理过程
- 链式构建示例:
java复制Handler chain = new StaffHandler(); chain.setNext(new ManagerHandler()) .setNext(new DirectorHandler());
2.2 处理流程示意图
code复制客户端请求 → HandlerA → HandlerB → HandlerC
| | |
处理条件A 处理条件B 处理条件C
↓ ↓ ↓
处理逻辑A 处理逻辑B 处理逻辑C
| | |
转交下一级 转交下一级 终止处理
关键设计原则:每个处理者只关注自己的职责范围,不知道也不关心整个链条的结构。这正是松耦合的精髓所在。
3. 实战:电商订单处理系统
让我们通过一个电商场景来具体实现责任链模式。假设我们需要处理订单的:
- 库存校验
- 风控审核
- 优惠计算
- 支付处理
3.1 定义抽象处理者
java复制public abstract class OrderHandler {
protected OrderHandler next;
// 链式设置后继者
public OrderHandler setNext(OrderHandler next) {
this.next = next;
return next;
}
// 处理请求
public abstract void handle(Order order);
// 传递给下一个处理器
protected void passToNext(Order order) {
if (next != null) {
next.handle(order);
}
}
}
3.2 实现具体处理者
库存处理器:
java复制public class InventoryHandler extends OrderHandler {
@Override
public void handle(Order order) {
if (!checkInventory(order)) {
throw new RuntimeException("库存不足");
}
System.out.println("库存校验通过");
passToNext(order);
}
private boolean checkInventory(Order order) {
// 实际库存检查逻辑
return true;
}
}
风控处理器:
java复制public class RiskHandler extends OrderHandler {
@Override
public void handle(Order order) {
if (isHighRisk(order)) {
throw new RuntimeException("风控拦截");
}
System.out.println("风控检查通过");
passToNext(order);
}
private boolean isHighRisk(Order order) {
// 实际风控逻辑
return false;
}
}
优惠处理器:
java复制public class DiscountHandler extends OrderHandler {
@Override
public void handle(Order order) {
applyDiscounts(order);
System.out.println("优惠计算完成");
passToNext(order);
}
private void applyDiscounts(Order order) {
// 优惠计算逻辑
}
}
3.3 客户端组装执行
java复制OrderHandler handlerChain = new InventoryHandler();
handlerChain.setNext(new RiskHandler())
.setNext(new DiscountHandler())
.setNext(new PaymentHandler());
Order order = new Order();
handlerChain.handle(order);
4. 高级应用技巧
4.1 动态调整处理链
在实际项目中,处理链可能需要动态调整。我们可以引入ChainManager来管理:
java复制public class ChainManager {
private OrderHandler head;
private OrderHandler tail;
public ChainManager addHandler(OrderHandler handler) {
if (head == null) {
head = handler;
tail = handler;
} else {
tail.setNext(handler);
tail = handler;
}
return this;
}
public void execute(Order order) {
if (head != null) {
head.handle(order);
}
}
}
// 使用示例
ChainManager manager = new ChainManager();
manager.addHandler(new InventoryHandler())
.addHandler(new RiskHandler())
.execute(order);
4.2 中断链式传递
有时需要在特定条件下中断处理链:
java复制public abstract class OrderHandler {
// ...其他代码...
protected boolean shouldContinue(Order order) {
// 默认继续传递
return true;
}
public final void handle(Order order) {
doHandle(order);
if (shouldContinue(order) && next != null) {
next.handle(order);
}
}
protected abstract void doHandle(Order order);
}
4.3 组合其他模式
责任链经常与其他模式配合使用:
-
与模板方法模式结合:
java复制public abstract class TemplateHandler { public final void handle(Request request) { if (canHandle(request)) { doHandle(request); } else { passToNext(request); } } protected abstract boolean canHandle(Request request); protected abstract void doHandle(Request request); protected abstract void passToNext(Request request); } -
与工厂模式结合动态创建处理链
5. 性能优化与注意事项
5.1 性能考量
-
链长度控制:
- 过长的处理链会影响性能
- 建议监控平均处理深度
- 解决方案:对高频请求使用缓存结果
-
异步处理:
java复制public class AsyncHandler extends OrderHandler { @Override public void handle(Order order) { CompletableFuture.runAsync(() -> { // 处理逻辑 passToNext(order); }); } }
5.2 常见陷阱
-
循环引用:
java复制Handler a = new HandlerA(); Handler b = new HandlerB(); a.setNext(b); b.setNext(a); // 危险!形成循环 -
请求丢失:
- 确保链条终点的处理
- 可以添加兜底处理器:
java复制public class DefaultHandler extends OrderHandler { @Override public void handle(Order order) { // 默认处理逻辑 System.out.println("请求未被任何处理器处理"); } }
-
异常处理:
- 统一异常处理机制
- 示例:
java复制public final void handle(Order order) { try { doHandle(order); passToNext(order); } catch (Exception e) { // 统一异常处理 } }
6. 框架中的责任链模式
6.1 Servlet Filter
最经典的责任链实现:
java复制public class LogFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
// 前置处理
chain.doFilter(req, res); // 传递给下一个filter
// 后置处理
}
}
6.2 Spring Interceptor
Spring MVC的拦截器链:
java复制public class AuthInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
// 返回true继续链,false中断
return checkAuth(request);
}
}
6.3 MyBatis Plugin
MyBatis的插件机制:
java复制@Intercepts(@Signature(type=Executor.class, method="update",
args={MappedStatement.class,Object.class}))
public class MyPlugin implements Interceptor {
public Object intercept(Invocation invocation) {
// 处理逻辑
return invocation.proceed(); // 继续链
}
}
7. 模式对比:责任链 vs 其他模式
7.1 责任链 vs 命令模式
| 特性 | 责任链 | 命令 |
|---|---|---|
| 核心思想 | 处理者链 | 封装请求 |
| 处理者数量 | 多个 | 通常一个 |
| 顺序重要性 | 关键 | 无关 |
| 典型应用 | 审批流 | 事务操作 |
7.2 责任链 vs 装饰器模式
虽然都有链式结构,但:
- 装饰器:增强原有功能
- 责任链:决定是否处理请求
7.3 责任链 vs 状态模式
状态模式:对象内部状态改变行为
责任链:外部处理器链决定行为
8. 最佳实践建议
-
明确处理边界:
- 每个处理器应有清晰的职责范围
- 避免"全能处理器"反模式
-
配置化链条:
- 将处理器顺序配置在外部(如数据库、配置文件)
- 示例配置:
yaml复制handlers: - com.example.InventoryHandler - com.example.RiskHandler - com.example.DiscountHandler
-
监控与诊断:
- 记录请求经过的处理器路径
- 添加处理器执行时间统计
-
测试策略:
- 单元测试每个处理器
- 集成测试完整链条
- 特别注意边界条件测试
-
文档规范:
- 为每个处理器编写清晰的职责说明
- 记录典型处理流程示例
我在实际项目中最深刻的教训是:不要过度设计处理链。曾经在一个物流系统中,我们设计了10多级的处理链,结果调试起来异常困难。后来重构为3个主链+子链的结构后,可维护性大大提升。记住,设计模式的目的是简化而不是复杂化系统。