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

责任链模式让你能把一整个处理流程拆成一节节的"处理器(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)


⏱ 四、时序图

Client H1 H2 handle(request) pass(request) handle(request) Client H1 H2


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

1)请求对象

java 复制代码
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)

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

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

java 复制代码
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)具体处理器:安全风控

java 复制代码
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)具体处理器:支付处理(最终处理)

java 复制代码
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)客户端组装链并执行

java 复制代码
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 的链式分发(伪代码思路)

java 复制代码
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(支持中途修改)

java 复制代码
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 指示是否继续

java 复制代码
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),记录每一步处理耗时与结果,便于线上排查。

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

java 复制代码
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),可以在不同环境快速组合不同流水线。


🔚 十三、总结

  • 责任链模式 非常适合把复杂的"先后处理逻辑"拆成可组合、可重排的单元。
  • 要注意链的性能、异常处理与生命周期管理。
  • 与工厂/策略模式联用能得到更灵活、可配置、企业级的处理流水线。
相关推荐
CodeAmaz2 小时前
使用责任链模式设计电商下单流程(Java 实战)
java·后端·设计模式·责任链模式·下单
大G的笔记本12 小时前
Java常见设计模式面试题(高频)
java·开发语言·设计模式
老鼠只爱大米12 小时前
Java设计模式之建造者模式(Builder)详解
java·设计模式·建造者模式·builder·23种设计模式
guangzan18 小时前
常用设计模式:职责链模式
设计模式
ZHE|张恒18 小时前
设计模式实战篇(二):业务逻辑“随时切换招式”——策略模式(Strategy Pattern)解析
设计模式·策略模式
小二·21 小时前
设计模式面试题(14道含答案)
设计模式
老鼠只爱大米1 天前
Java 设计模式之适配器模式:系统集成的万能接口
java·设计模式·适配器模式·adapter·java设计模式
o0向阳而生0o1 天前
112、23种设计模式之命令模式(20/23)
设计模式·命令模式
将编程培养成爱好1 天前
C++ 设计模式《外卖骑手状态系统》
c++·ui·设计模式·状态模式