C++设计模式之行为型模式:职责链模式(Chain of Responsibility)

职责链模式(Chain of Responsibility)是行为型设计模式的一种,它通过将请求的发送者与接收者解耦,使多个接收者(处理者)组成一条链,请求在链上传递,直到被某个处理者处理。这种模式避免了请求发送者与具体处理者的直接耦合,允许动态调整处理链。

一、核心思想与角色

职责链模式的核心是"请求沿链传递,谁能处理谁处理",通过构建处理者链条实现请求的分发。其核心角色如下:

角色名称 核心职责
抽象处理者(Handler) 定义处理请求的接口,包含一个指向后继处理者的引用,声明处理请求的方法。
具体处理者(ConcreteHandler) 实现抽象处理者接口,判断自身是否能处理请求:能处理则处理,否则将请求转发给后继者。
客户端(Client) 创建处理者链条,并向链的第一个处理者发送请求,无需关心具体谁处理了请求。

核心思想:将多个处理者串联成链,请求从链的起点开始传递,每个处理者自行决定是否处理请求或转发给下一个处理者,从而实现请求与处理的解耦。

二、实现示例(请假审批系统)

假设公司的请假审批流程为:

  • 请假≤1天:组长审批
  • 1天<请假≤3天:部门经理审批
  • 3天<请假≤7天:总监审批
  • 请假>7天:总经理审批

使用职责链模式可灵活构建审批流程:

cpp 复制代码
#include <iostream>
#include <string>

// 请假请求
class LeaveRequest {
private:
    std::string employeeName; // 员工姓名
    int days;                 // 请假天数

public:
    LeaveRequest(const std::string& name, int d) 
        : employeeName(name), days(d) {}

    std::string getEmployeeName() const { return employeeName; }
    int getDays() const { return days; }
};

// 1. 抽象处理者:审批者
class Approver {
protected:
    Approver* nextApprover; // 后继审批者(职责链的下一个节点)

public:
    // 构造函数:初始化后继审批者
    Approver(Approver* next) : nextApprover(next) {}

    virtual ~Approver() {
        // 递归释放整条链(避免内存泄漏)
        delete nextApprover;
        nextApprover = nullptr;
    }

    // 纯虚方法:处理请假请求
    virtual void processRequest(const LeaveRequest& request) = 0;
};

// 2. 具体处理者1:组长(处理≤1天的请假)
class TeamLeader : public Approver {
public:
    TeamLeader(Approver* next) : Approver(next) {}

    void processRequest(const LeaveRequest& request) override {
        if (request.getDays() <= 1) {
            // 能处理:直接审批
            std::cout << "组长审批了" << request.getEmployeeName() 
                      << "的" << request.getDays() << "天请假" << std::endl;
        } else if (nextApprover) {
            // 不能处理:转发给下一个审批者
            nextApprover->processRequest(request);
        } else {
            // 无后继者:无法审批
            std::cout << "无人能审批" << request.getEmployeeName() 
                      << "的" << request.getDays() << "天请假" << std::endl;
        }
    }
};

// 2. 具体处理者2:部门经理(处理1~3天的请假)
class DepartmentManager : public Approver {
public:
    DepartmentManager(Approver* next) : Approver(next) {}

    void processRequest(const LeaveRequest& request) override {
        if (request.getDays() > 1 && request.getDays() <= 3) {
            std::cout << "部门经理审批了" << request.getEmployeeName() 
                      << "的" << request.getDays() << "天请假" << std::endl;
        } else if (nextApprover) {
            nextApprover->processRequest(request);
        } else {
            std::cout << "无人能审批" << request.getEmployeeName() 
                      << "的" << request.getDays() << "天请假" << std::endl;
        }
    }
};

// 2. 具体处理者3:总监(处理3~7天的请假)
class Director : public Approver {
public:
    Director(Approver* next) : Approver(next) {}

    void processRequest(const LeaveRequest& request) override {
        if (request.getDays() > 3 && request.getDays() <= 7) {
            std::cout << "总监审批了" << request.getEmployeeName() 
                      << "的" << request.getDays() << "天请假" << std::endl;
        } else if (nextApprover) {
            nextApprover->processRequest(request);
        } else {
            std::cout << "无人能审批" << request.getEmployeeName() 
                      << "的" << request.getDays() << "天请假" << std::endl;
        }
    }
};

// 2. 具体处理者4:总经理(处理>7天的请假)
class GeneralManager : public Approver {
public:
    GeneralManager(Approver* next) : Approver(next) {}

    void processRequest(const LeaveRequest& request) override {
        if (request.getDays() > 7) {
            std::cout << "总经理审批了" << request.getEmployeeName() 
                      << "的" << request.getDays() << "天请假" << std::endl;
        } else if (nextApprover) {
            nextApprover->processRequest(request);
        } else {
            std::cout << "无人能审批" << request.getEmployeeName() 
                      << "的" << request.getDays() << "天请假" << std::endl;
        }
    }
};

// 客户端代码:构建审批链并发起请求
int main() {
    // 构建职责链:组长 → 部门经理 → 总监 → 总经理
    Approver* chain = new TeamLeader(
        new DepartmentManager(
            new Director(
                new GeneralManager(nullptr) // 链的末尾
            )
        )
    );

    // 发起不同天数的请假请求
    LeaveRequest req1("张三", 1);   // 组长审批
    LeaveRequest req2("李四", 2);   // 部门经理审批
    LeaveRequest req3("王五", 5);   // 总监审批
    LeaveRequest req4("赵六", 10);  // 总经理审批
    LeaveRequest req5("钱七", 0);   // 组长审批(特殊情况)

    chain->processRequest(req1);
    chain->processRequest(req2);
    chain->processRequest(req3);
    chain->processRequest(req4);
    chain->processRequest(req5);

    // 释放链条(会递归释放所有处理者)
    delete chain;

    return 0;
}

三、代码解析

  1. 请求对象(LeaveRequest):封装请假信息(员工姓名、天数),作为处理者的处理参数。

  2. 抽象处理者(Approver)

    • 包含nextApprover指针,指向链中的下一个处理者。
    • 声明纯虚方法processRequest(),定义处理请求的接口。
    • 析构函数递归释放整条链,避免内存泄漏。
  3. 具体处理者

    每个处理者(TeamLeaderDepartmentManager等)实现processRequest()方法,根据自身职责范围决定是否处理请求:

    • 若请求在自身处理范围内(如组长处理≤1天的请假),则直接处理。
    • 若不在范围内且存在后继处理者,则转发请求(nextApprover->processRequest(request))。
    • 若不在范围内且无后继者,则提示无法处理。
  4. 客户端构建链条

    客户端通过嵌套构造函数创建处理者链条(组长→部门经理→总监→总经理),并向链的第一个处理者发送请求,无需关心具体由谁处理。

四、核心优势与适用场景

优势
  1. 解耦请求与处理:请求发送者无需知道谁处理了请求,处理者也无需知道请求的来源,降低耦合度。
  2. 动态调整链条:可通过增删处理者或改变顺序动态调整处理流程(如临时跳过部门经理审批)。
  3. 单一职责:每个处理者只负责自己范围内的请求,符合单一职责原则。
  4. 灵活性:新处理者可随时加入链中,无需修改现有代码(符合开闭原则)。
适用场景
  1. 存在多个处理者,且处理范围明确:如审批流程、日志级别处理(DEBUG→INFO→WARN→ERROR)。
  2. 请求的处理者不确定:请求发送时不知道谁会处理,需动态决定。
  3. 需要动态调整处理流程:如根据业务规则临时改变处理顺序或增减处理步骤。

五、与其他模式的区别

模式 核心差异点
职责链模式 请求沿链传递,由第一个能处理的对象处理,强调"请求分发与传递"。
命令模式 将请求封装为对象,可参数化、队列化请求,强调"请求的封装与执行"。
观察者模式 一个对象改变时通知多个观察者,所有观察者都会处理通知,而非选择一个处理。
状态模式 对象状态变化时改变行为,处理逻辑与状态绑定,而非沿链传递。

六、实践建议

  1. 明确处理范围:每个处理者的职责范围应清晰,避免重叠或遗漏导致请求无法处理。
  2. 设置默认处理者:在链的末尾添加默认处理者,确保所有请求都能被处理(或给出明确提示)。
  3. 避免过长链条:链条过长可能导致请求传递效率低,可通过分组或层级优化。
  4. 支持动态调整:设计时考虑允许运行时修改链条(如添加、移除或重新排序处理者)。

职责链模式的核心价值在于"灵活分发请求,解耦发送者与处理者"。它通过构建处理者链条,使请求能自动找到合适的处理者,同时支持动态调整处理流程,是处理具有层级关系或多步骤审批场景的理想选择。

相关推荐
勇闯逆流河2 小时前
【C++】AVL详解
开发语言·c++
长安——归故李3 小时前
【PLC程序学习】
java·c语言·javascript·c++·python·学习·php
青草地溪水旁3 小时前
设计模式(C++)详解——迭代器模式(4)
c++·设计模式·迭代器模式
大飞pkz3 小时前
【设计模式】状态模式
开发语言·设计模式·c#·状态模式
笨手笨脚の3 小时前
设计模式-建造者模式
java·设计模式·建造者模式·创建型设计模式
Jiezcode3 小时前
LeetCode 48. 旋转图像
c++·算法·leetcode·职场和发展
咔咔咔的3 小时前
165. 比较版本号
c++
charlie1145141914 小时前
精读C++20设计模式——创造型设计模式:单例模式
c++·学习·单例模式·设计模式·c++20
高山有多高4 小时前
C语言实战项目:贪吃蛇(2)
c语言·开发语言·数据结构·c++·算法·游戏·游戏设计