设计模式实战篇(五):责任链模式 — 把繁琐审批/过滤流程变成可组合的“传递链”

责任链模式让你能把一整个处理流程拆成一节节的“处理器(Handler)”,按链条传递请求,减少 if/else、增强可扩展性。
适用场景:审批流、拦截器链、日志过滤、异常处理器、消息处理流水线。


一、责任链模式是什么?

责任链模式(Chain of Responsibility)定义一系列处理者(Handler),每个处理者决定:

  • 自己处理请求或
  • 把请求传给下一个处理者

优点:

  • 解耦请求发送者与处理者
  • 支持动态组装处理链(运行时)
  • 支持短路(某一节处理后终止)或透传(所有处理器都处理)

二、流程图

pass
pass
handled
Request
Handler1
Handler2
Handler3
Response

三、UML 类图

«abstract»
Handler
-Handler next
+setNext(Handler)
+handle(Request)
ConcreteHandlerA
+handle(Request)
ConcreteHandlerB
+handle(Request)

⏱ 四、时序图

ClientH1H2handle(request)pass(request)handle(request)ClientH1H2

五、场景:订单校验与处理链

1)请求对象

public class OrderRequest {
private final String orderId;
private final double amount;
private final String userId;
public OrderRequest(String orderId, double amount, String userId) {
this.orderId = orderId;
this.amount = amount;
this.userId = userId;
}
public String getOrderId() { return orderId; }
public double getAmount() { return amount; }
public String getUserId() { return userId; }
}

2)抽象处理器(Handler)

public abstract class Handler {
protected Handler next;
public Handler setNext(Handler next) {
this.next = next;
return next;
}
public abstract void handle(OrderRequest request);
}

3)具体处理器:校验库存

public class InventoryHandler extends Handler {
@Override
public void handle(OrderRequest request) {
System.out.println("InventoryHandler 检查库存 for " + request.getOrderId());
boolean ok = true; // 假设检查逻辑
if (!ok) {
System.out.println("库存不足,终止处理");
return; // 终止链
}
if (next != null) next.handle(request);
}
}

4)具体处理器:安全风控

public class FraudCheckHandler extends Handler {
@Override
public void handle(OrderRequest request) {
System.out.println("FraudCheckHandler 风控检查 for " + request.getOrderId());
boolean suspicious = false; // 假设判断
if (suspicious) {
System.out.println("疑似风险,通知人工");
return; // 终止链或转人工
}
if (next != null) next.handle(request);
}
}

5)具体处理器:支付处理(最终处理)

public class PaymentHandler extends Handler {
@Override
public void handle(OrderRequest request) {
System.out.println("PaymentHandler 执行支付 for " + request.getOrderId()
+ " amount=" + request.getAmount());
// 支付逻辑...
if (next != null) next.handle(request);
}
}

6)客户端组装链并执行

public class Main {
public static void main(String[] args) {
Handler inventory = new InventoryHandler();
Handler fraud = new FraudCheckHandler();
Handler payment = new PaymentHandler();
inventory.setNext(fraud).setNext(payment);
OrderRequest req = new OrderRequest("order-1001", 199.9, "user-01");
inventory.handle(req);
}
}

六、责任链的变体与典型落地()

  • 链表式(经典): 每个 Handler 保存下一个 Handler 的引用。

  • 数组/列表式(Dispatcher): 把处理器放入集合,统一遍历调用。便于动态调整顺序与并行化。

  • 过滤器链(Servlet Filter): 支持 “前处理 -> 调用链 -> 后处理” 模式(典型的 AOP 风格)。

  • 返回值式链: 每个处理器返回一个结果对象,调用端据此决定是否继续。

典型应用:

  • 请求拦截器(认证、限流、日志、限速)
  • 审批流(逐级审批)
  • 消息处理流水线(解密->解压->校验->路由)
  • 中间件插件链(如 ElasticSearch 插件链)

七、Spring 风格的责任链(Filter / Interceptor 思路)

1)基于 List 的链式分发(伪代码思路)

public class ChainDispatcher {
private final List<Handler> handlers;
  public ChainDispatcher(List<Handler> handlers) {
    this.handlers = handlers;
    }
    public void dispatch(OrderRequest req) {
    for (Handler h : handlers) {
    h.handle(req);
    // optionally break if req marked handled
    }
    }
    }

在 Spring 中,这类链通常以 FilterRegistrationBeanHandlerInterceptorOncePerRequestFilter 形式实现,且可通过配置动态增删。


八、带上下文与短路/回调的实现

1)带上下文的 Request/Response(支持中途修改)

public class Context {
private final Map<String, Object> data = new HashMap<>();
  private boolean handled = false;
  public void put(String k, Object v) { data.put(k, v); }
  public Object get(String k) { return data.get(k); }
  public boolean isHandled() { return handled; }
  public void setHandled(boolean handled) { this.handled = handled; }
  }

2)Handler 返回 boolean 指示是否继续

public abstract class AdvancedHandler {
protected AdvancedHandler next;
public AdvancedHandler setNext(AdvancedHandler next) {
this.next = next;
return next;
}
/**
* 返回 true 表示继续传递,false 表示中断
*/
public abstract boolean handle(Context ctx);
}

⚠️ 九、错误与反模式

  • 把链写成 if/else: 绕回了模式初衷。
  • 链长度不可控时性能问题: 每个处理器都做同步耗时操作会拖慢请求。建议异步或并行化。
  • 观察者与责任链混用混淆: 观察者用于广播通知,责任链用于请求逐级处理,职责不同。
  • 忘记处理异常: 某一节点抛异常可能中断链而未做补偿,需统一异常策略或回滚策略。

十、组合模式:职责链 + 策略 + 工厂

  • 用工厂创建 Handler: 不同环境用不同处理器集合;用工厂负责 Handler 的创建与注入。
  • 用策略决定是否中断: 在 Handler 内部用策略模式决定是否继续传递。
  • 用责任链组织多个策略的执行顺序: 把策略作为链上的 Handler。

十一、测试与调试建议

  • 单测每个 Handler 的独立行为,注入 Mock 依赖。
  • 集成测试链条顺序与短路逻辑。
  • 在链中加入可切换的调试开关(trace id / log),记录每一步处理耗时与结果,便于线上排查。

十二、示例:把责任链做成可配置流水线(伪实现)

public class Pipeline {
private final List<Handler> handlers;
  public Pipeline(List<Handler> handlers) { this.handlers = handlers; }
    public void process(OrderRequest req) {
    for (Handler h : handlers) {
    h.handle(req);
    // 如果某个 handler 设置了中断标识,则 break
    }
    }
    }

通过注入不同 Handler 列表(来自配置或 Spring),可以在不同环境快速组合不同流水线。


十三、总结

  • 责任链模式 非常适合把复杂的“先后处理逻辑”拆成可组合、可重排的单元。
  • 要注意链的性能、异常处理与生命周期管理。
  • 与工厂/策略模式联用能得到更灵活、可配置、企业级的处理流水线。
posted @ 2025-12-13 08:05  yangykaifa  阅读(20)  评论(0)    收藏  举报