责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许将请求沿着处理者链进行传递,直到有一个处理者处理它为止。这种模式通过为请求创建一个接收者对象链,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。

责任链模式的核心角色

  1. 抽象处理者(Handler):定义处理请求的接口,包含一个指向后续处理者的引用
  2. 具体处理者(Concrete Handler):实现处理请求的接口,如果可以处理请求则处理,否则将请求传递给下一个处理者
  3. 客户端(Client):创建处理者链,并向链的第一个处理者提交请求

责任链模式的实现示例

下面以"请假审批流程"为例展示责任链模式的实现,不同天数的请假需要不同层级的领导审批:

#include <iostream>
#include <string>

// 抽象处理者:审批者
class Approver {
protected:
    Approver* nextApprover;  // 下一个审批者
    std::string name;       // 审批者姓名

public:
    Approver(const std::string& approverName, Approver* next = nullptr)
        : name(approverName), nextApprover(next) {}

    virtual ~Approver() {
        // 递归删除责任链
        delete nextApprover;
        nextApprover = nullptr;
    }

    // 处理请求的接口
    virtual void processRequest(int days) = 0;
};

// 具体处理者:组长(审批1-3天假期)
class TeamLeader : public Approver {
public:
    TeamLeader(const std::string& name, Approver* next = nullptr)
        : Approver(name, next) {}

    void processRequest(int days) override {
        if (days <= 3) {
            std::cout << "组长 " << name << " 批准了 " << days << " 天假期" << std::endl;
        } else if (nextApprover) {
            std::cout << "组长 " << name << " 无法批准 " << days << " 天假期,提交给上一级" << std::endl;
            nextApprover->processRequest(days);
        } else {
            std::cout << "无人可以批准 " << days << " 天假期" << std::endl;
        }
    }
};

// 具体处理者:部门经理(审批4-7天假期)
class DepartmentManager : public Approver {
public:
    DepartmentManager(const std::string& name, Approver* next = nullptr)
        : Approver(name, next) {}

    void processRequest(int days) override {
        if (days <= 7) {
            std::cout << "部门经理 " << name << " 批准了 " << days << " 天假期" << std::endl;
        } else if (nextApprover) {
            std::cout << "部门经理 " << name << " 无法批准 " << days << " 天假期,提交给上一级" << std::endl;
            nextApprover->processRequest(days);
        } else {
            std::cout << "无人可以批准 " << days << " 天假期" << std::endl;
        }
    }
};

// 具体处理者:总经理(审批8-30天假期)
class GeneralManager : public Approver {
public:
    GeneralManager(const std::string& name, Approver* next = nullptr)
        : Approver(name, next) {}

    void processRequest(int days) override {
        if (days <= 30) {
            std::cout << "总经理 " << name << " 批准了 " << days << " 天假期" << std::endl;
        } else if (nextApprover) {
            std::cout << "总经理 " << name << " 无法批准 " << days << " 天假期,提交给上一级" << std::endl;
            nextApprover->processRequest(days);
        } else {
            std::cout << days << " 天假期超出审批权限,不予批准" << std::endl;
        }
    }
};

// 客户端使用
int main() {
    // 创建审批者链:组长 -> 部门经理 -> 总经理
    Approver* generalManager = new GeneralManager("王总");
    Approver* deptManager = new DepartmentManager("李经理", generalManager);
    Approver* teamLeader = new TeamLeader("张组长", deptManager);

    // 提交不同天数的请假请求
    std::cout << "=== 请假 2 天 ===" << std::endl;
    teamLeader->processRequest(2);

    std::cout << "\n=== 请假 5 天 ===" << std::endl;
    teamLeader->processRequest(5);

    std::cout << "\n=== 请假 15 天 ===" << std::endl;
    teamLeader->processRequest(15);

    std::cout << "\n=== 请假 40 天 ===" << std::endl;
    teamLeader->processRequest(40);

    // 清理资源(递归删除整个链)
    delete teamLeader;

    return 0;
}

责任链模式的工作原理

  1. 每个处理者都包含对下一个处理者的引用,形成一条链
  2. 当有请求发生时,请求被提交到链的第一个处理者
  3. 每个处理者判断自己是否可以处理该请求:
    • 如果可以处理,则处理请求并终止链传递
    • 如果不能处理,则将请求传递给下一个处理者
  4. 如果请求到达链的末尾仍未被处理,则可能被忽略或由系统处理

责任链的两种组织方式

  • 线性链:每个处理者只知道下一个处理者(如示例所示)
  • 树形链:每个处理者可以有多个后续处理者,形成更复杂的处理网络

责任链模式与其他模式的区别

  • 责任链模式:请求沿链传递,由第一个能处理的对象处理
  • 命令模式:请求被封装为对象,可以被存储、排队和撤销
  • 中介者模式:通过一个中心对象协调多个对象的交互

责任链模式的应用场景

  1. 当有多个对象可以处理同一请求,且具体哪个对象处理由运行时决定时
  2. 当希望在不明确指定接收者的情况下,向多个对象中的一个提交请求时
  3. 当需要动态指定处理请求的对象集合时

责任链模式的优缺点

优点

  • 降低了请求发送者和接收者之间的耦合度
  • 可以动态调整责任链中的处理者,增加或删除处理者
  • 每个处理者只需要关注自己能处理的请求,职责单一
  • 符合开放-封闭原则,新增处理者无需修改现有代码

缺点

  • 请求可能未被任何处理者处理,需要有相应的容错机制
  • 对于长链,请求的处理可能存在性能问题
  • 调试较复杂,需要跟踪整个链的执行过程

责任链模式在实际开发中应用广泛,例如:

  • 日志系统(不同级别日志由不同处理器处理)
  • 事件冒泡机制(GUI中的事件传递)
  • 过滤器链(Web框架中的请求过滤)
  • 权限控制系统(不同角色有不同审批权限)

这种模式通过将请求的发送者与多个可能的接收者解耦,提高了系统的灵活性和可扩展性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐