Skip to content

责任链模式(Chain of Responsibility Pattern)笔记

定义

责任链模式是一种行为设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

英文原文定义

The Chain of Responsibility Pattern avoids coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

核心概念

责任链模式通过建立处理对象的链式结构,使请求可以沿着链传递,直到被某个处理者处理。这种模式实现了请求发送者和接收者的解耦。

主要角色

  1. Handler(抽象处理者):定义处理请求的接口,通常包含设置后继者的方法
  2. ConcreteHandler(具体处理者):实现处理请求的具体逻辑,可以访问后继者
  3. Client(客户端):创建处理链,并向链头的处理者提交请求

优缺点

优点

  • 降低耦合度:请求发送者不需要知道哪个对象会处理请求
  • 动态灵活:可以在运行时动态改变链中的处理者或它们的顺序
  • 单一职责原则:每个处理者只需关注自己处理的请求
  • 开闭原则:可以新增处理者而不修改现有代码

缺点

  • 请求可能未被处理:如果链配置不当,请求可能到达链尾都未被处理
  • 性能影响:较长的责任链可能影响性能(可通过非纯责任链优化)
  • 调试困难:请求的传递过程可能使调试变得复杂

解决的问题

责任链模式主要解决以下经典问题:

  1. 多条件流程处理:当需要多个条件判断分支处理请求时
  2. 动态指定处理者:当处理请求的对象需要动态指定时
  3. 解耦请求发送者和接收者:当不希望明确指定请求接收者时
  4. 审批流程:多级审批、权限检查等场景

实现注意事项

  1. 链的构建方式

    • 客户端显式构建(更灵活)
    • 处理者自组织构建(更内聚)
  2. 请求传递控制

    • 纯责任链:必须被某个处理者处理
    • 非纯责任链:允许不被处理
  3. 后继者引用

    • 可以定义在抽象处理者中(所有子类共享)
    • 也可以由具体处理者自行维护
  4. 请求对象设计

    • 包含处理所需的所有信息
    • 可以考虑包含处理状态
  5. 性能优化

    • 对于长链,可以考虑短路处理(提前终止)
    • 缓存常用处理路径

实现变体

  1. 纯责任链

    • 请求必须被处理
    • 每个处理者要么处理请求,要么传递给下一个
  2. 非纯责任链

    • 请求可能不被处理
    • 更常见于实际应用
  3. 功能链

    • 每个处理者对请求进行部分处理
    • 类似于管道过滤器模式
  4. 树形结构链

    • 处理者形成树形结构
    • 请求可以沿多个路径传递

与其他模式的关系

相似模式区分

  1. 装饰器模式

    • 责任链:处理者决定是否处理请求
    • 装饰器:所有装饰者都会参与处理
  2. 命令模式

    • 责任链:多个处理者选择执行
    • 命令:将请求封装为对象
  3. 组合模式

    • 责任链:处理者形成链式结构
    • 组合:处理者形成树形结构

常见搭配组合

  1. 责任链 + 组合:构建树形处理结构
  2. 责任链 + 策略:不同处理者使用不同策略
  3. 责任链 + 模板方法:处理流程中应用模板方法
  4. 责任链 + 享元:共享处理者实例

典型应用场景

  • 异常处理(try-catch-finally块)
  • 事件冒泡(GUI事件处理)
  • 审批工作流(采购审批、请假审批)
  • Web请求过滤器(Servlet Filter)
  • 日志记录器(不同级别的日志处理)
  • 游戏中的输入处理

代码示例(请假审批实现)

java
// 抽象处理者
abstract class Approver {
    protected Approver successor;
    
    public void setSuccessor(Approver successor) {
        this.successor = successor;
    }
    
    public abstract void processRequest(LeaveRequest request);
}

// 具体处理者:主管
class Supervisor extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 3) {
            System.out.println("Supervisor approved leave for " + request.getDays() + " days");
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}

// 具体处理者:经理
class Manager extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 10) {
            System.out.println("Manager approved leave for " + request.getDays() + " days");
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}

// 具体处理者:总监
class Director extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        System.out.println("Director approved leave for " + request.getDays() + " days");
    }
}

// 请求类
class LeaveRequest {
    private int days;
    private String reason;
    
    // 构造方法和getter省略
}

// 客户端代码
Approver supervisor = new Supervisor();
Approver manager = new Manager();
Approver director = new Director();

supervisor.setSuccessor(manager);
manager.setSuccessor(director);

LeaveRequest request1 = new LeaveRequest(2, "Family event");
supervisor.processRequest(request1);

LeaveRequest request2 = new LeaveRequest(5, "Medical leave");
supervisor.processRequest(request2);