Skip to content

职责链模式

引言

在软件系统中,当请求需要多级审批(如报销流程)或动态路由(如HTTP中间件)时,硬编码处理逻辑会导致代码臃肿可扩展性差。职责链模式通过将处理对象连成链条,实现请求的自动化传递按需处理,成为解耦请求与处理的经典解决方案。

诞生背景

GoF在《设计模式》中提出职责链模式,解决三大痛点:

  • 处理逻辑僵化:新增处理步骤需修改核心代码(如风控系统增加新规则)
  • 请求发送者臃肿:客户端需显式调用所有处理器(如订单状态机调用10+校验器)
  • 动态路由缺失:无法运行时调整处理流程(如日志过滤链动态开关)

演进过程

  • GoF基础(1994):确立处理器链与传递机制
  • Web框架演进:HTTP中间件链(Express.js的next(),Spring Interceptor)
  • 现代应用:微服务网关的过滤器链(Spring Cloud Gateway)

核心概念

  • 抽象处理器(Handler):定义处理接口与后继链设置方法
  • 具体处理器(Concrete Handler):实现请求处理逻辑与传递机制
  • 客户端(Client):初始化处理链并提交请求

通用实现

Java 实现

java
// 抽象处理器
abstract class Handler {
    protected Handler next;
    
    public void setNext(Handler next) {
        this.next = next;
    }
    
    public abstract void handleRequest(int request);
}

// 具体处理器:级别1
class ConcreteHandler1 extends Handler {
    public void handleRequest(int request) {
        if (request <= 10) {
            System.out.println("Handler1 processed: " + request);
        } else if (next != null) {
            next.handleRequest(request); // 传递请求
        }
    }
}

// 具体处理器:级别2
class ConcreteHandler2 extends Handler {
    public void handleRequest(int request) {
        if (request <= 20) {
            System.out.println("Handler2 processed: " + request);
        } else if (next != null) {
            next.handleRequest(request);
        }
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Handler chain = new ConcreteHandler1();
        chain.setNext(new ConcreteHandler2());
        
        chain.handleRequest(5);  // Handler1处理
        chain.handleRequest(15); // Handler2处理
    }
}

PHP 实现

php
// 抽象处理器
abstract class Handler {
    protected ?Handler $next = null;
    
    public function setNext(Handler $next): void {
        $this->next = $next;
    }
    
    abstract public function handleRequest(int $request): void;
}

// 具体处理器:日志过滤器
class LogFilter extends Handler {
    public function handleRequest(int $request): void {
        if ($request > 100) {
            echo "LogFilter: Request too large\n";
        } else if ($this->next) {
            $this->next->handleRequest($request);
        }
    }
}

// 具体处理器:权限校验
class AuthHandler extends Handler {
    public function handleRequest(int $request): void {
        if ($request < 0) {
            echo "AuthHandler: Invalid request\n";
        } else if ($this->next) {
            $this->next->handleRequest($request);
        }
    }
}

// 客户端
$chain = new LogFilter();
$chain->setNext(new AuthHandler());

$chain->handleRequest(50); // 通过所有处理器
$chain->handleRequest(150); // LogFilter拦截

应用场景

  • 多级审批系统:报销流程(员工→经理→财务)
  • 请求过滤链:Web中间件(鉴权→日志→缓存)
  • 异常处理:错误捕获链(业务异常→系统异常→全局兜底)
  • 游戏事件处理:伤害计算链(防御减免→暴击判定)

案例:订单风控系统

Java 实现

java
// 风控处理器基类
abstract class RiskHandler {
    protected RiskHandler next;
    public void setNext(RiskHandler next) { this.next = next; }
    public abstract void check(Order order);
}

// 具体处理器:黑名单校验
class BlacklistHandler extends RiskHandler {
    public void check(Order order) {
        if (order.user.isBlacklisted()) {
            System.out.println("BLOCKED: User in blacklist");
        } else if (next != null) {
            next.check(order); // 传递订单
        }
    }
}

// 具体处理器:金额校验
class AmountHandler extends RiskHandler {
    public void check(Order order) {
        if (order.amount > 10000) {
            System.out.println("ALERT: Large amount order");
        } else if (next != null) {
            next.check(order);
        }
    }
}

// 客户端使用
RiskHandler chain = new BlacklistHandler();
chain.setNext(new AmountHandler());
chain.check(order); // 自动触发风控链

PHP 实现

php
// 抽象日志处理器
abstract class LogHandler {
    protected ?LogHandler $next = null;
    public function setNext(LogHandler $next): void {
        $this->next = $next;
    }
    abstract public function process(string $log): void;
}

// 具体处理器:错误日志
class ErrorHandler extends LogHandler {
    public function process(string $log): void {
        if (str_contains($log, "ERROR")) {
            echo "Error logged to file\n";
        } else if ($this->next) {
            $this->next->process($log);
        }
    }
}

// 具体处理器:调试日志
class DebugHandler extends LogHandler {
    public function process(string $log): void {
        if (str_contains($log, "DEBUG")) {
            echo "Debug info sent to console\n";
        } else if ($this->next) {
            $this->next->process($log);
        }
    }
}

// 客户端
$chain = new ErrorHandler();
$chain->setNext(new DebugHandler());
$chain->process("DEBUG: User logged in"); // 触发DebugHandler

优点

  • 动态解耦:新增处理器无需修改客户端
  • 灵活扩展:运行时动态调整处理链顺序
  • 单一职责:每个处理器专注独立逻辑
  • 请求路由:自动选择匹配的处理者

缺点

  • 性能风险:长链导致请求传递开销
  • 调试困难:请求在链中“隐身”传递
  • 循环依赖:链配置错误引发死循环
  • 处理不确定性:请求可能未被任何处理器消费

扩展

  • 中断机制:处理器可中断传递(如Spring MVC拦截器返回false
  • 双向链条:支持请求反向传递(如异常处理链)
  • 链工厂模式:封装复杂链的构建过程
  • 异步职责链:处理器异步消费请求(如Akka Actor模型)

模式协作

  • 与组合模式:构建树形处理链(如XML解析器)
  • 与命令模式:将请求封装为可传递对象
  • 与装饰器模式:动态增强处理器能力
  • 与观察者模式:实现事件广播链(如Spring事件机制)

延伸思考

  • 微服务治理:API网关路由链(鉴权→限流→熔断)
  • 前端应用:表单校验链(必填项→格式校验→异步验证)
  • 性能优化
    • 短路处理(如校验失败立即终止)
    • 并行执行链(如ForkJoinPool拆分任务)
  • 反模式警示:避免构建“神链”(超过10个处理器的超长链)

总结

职责链模式是动态路由的编织者,通过解耦请求发送与处理逻辑,实现“流水线式”的请求处理。其核心价值在于:灵活可扩展的流程编排优雅的责任分离。在中间件系统、审批工作流等场景中,职责链模式能显著提升系统可维护性,成为行为设计模式中的“流程引擎”。