当前位置: 首页 > article >正文

实战设计模式之责任链模式

概述

        与上一篇介绍的命令模式一样,责任链模式也是一种行为设计模式,它允许我们将请求沿着处理者链进行传递。接收者和发送者都没有对方的引用,且责任链中的节点可以动态地添加或移除。这样,就避免了请求发送者与多个接收者的硬编码依赖,使系统更加灵活。

        在下面三种应用场景中,我们可以毫不犹豫地使用责任链模式。

        1、有多个对象可以处理一个请求,但事先并不确定哪个对象会真正处理该请求,我们可以根据运行时信息来决定。

        2、想要在不明确指定接收者的情况下,向多个对象中的一个提交请求,即发送者不需要知道是谁最终处理了请求。

        3、可以在不影响其他对象的情况下,动态地指定一组对象来处理请求。这意味着,我们可以随时调整链条上的处理者。

        公司的审批流程是现实生活中运用责任链模式的一个典型例子:当员工提交一份报销单时,这份报销单可能会先经过部门经理的初步审核,然后是财务部门的进一步检查,最后可能是高层管理人员的最终批准。每个级别的审批人员都有权决定是否批准该报销单,或者将其转发给更高级别的审批人。

基本原理

        责任链模式的核心思想在于:将请求的发送者与接收者进行解耦,通过建立一条链式结构,使得请求可以在链上的节点之间传递,直到有节点能够处理该请求为止。如果所有节点都无法处理,则请求可能最终未被处理或返回默认结果。责任链模式主要由以下三个核心组件构成。

        1、抽象处理器。定义了一个接口,所有具体处理器都必须实现这个接口。通常情况下,抽象处理器会包含下面两个方法。

        (1)SetNext:用于设置责任链中的下一个处理器。

        (2)Handle:用于处理请求,如果当前处理器不能处理,则调用链中下一个处理器的Handle方法继续处理。

        2、具体处理器。实现了抽象处理器的接口,提供了具体的业务逻辑来处理请求。每个具体处理器都决定自己是否能处理传入的请求,如果不能处理,则将请求转发给链中的下一个处理器。

        3、客户端。创建并组装处理器链,然后向链的起点提交请求。客户端不需要知道链的具体结构,只需要知道如何启动处理流程即可。

        基于上面的核心组件,责任链模式的实现主要有以下四个步骤。

        1、定义抽象处理器。创建一个基类或接口,定义了处理请求的方法,以及设置下一个处理器的方法。

        2、创建具体处理器。为每种类型的请求创建具体的处理器类,继承自抽象处理器,并实现处理逻辑。在Handle方法中,检查是否能处理请求。若不能,则调用链中的下一个处理器。

        3、构建责任链。在客户端中,实例化各个具体处理器,并使用SetNext方法将它们链接起来,形成责任链。

        4、发起请求。客户端只需向责任链的起点提交请求,而无需关心链的具体结构或长度。

实战解析

        在下面的实战代码中,我们使用责任链模式实现了公司的审批流程。

        首先,我们定义了抽象处理器类CHandler。CHandler定义了处理请求的基本框架,包含一个指向下一个处理器的指针m_pNext,以及设置下一个处理器的方法SetNext。同时,它还提供了一个虚函数Handle,用于处理请求或将其传递给下一个处理器。

        然后,我们定义了三个具体处理器类。CDepartmentManager表示部门经理,可以批准金额小于等于1000美元的请求。CFinanceManager表示财务经理,可以批准金额小于等于5000美元的请求。CCeo表示CEO,可以批准任何金额的请求,但通常只处理超过5000美元的请求。

        最后,在main函数中,我们创建了三个具体的处理器实例:部门经理、财务经理和CEO,并使用SetNext方法将这些处理器链接成一条责任链。我们向责任链发送了多个请求,每个请求都从链的起点(即部门经理)开始处理,直到找到能够处理该请求的处理器,或到达链的末端。

#include <iostream>
#include <string>

using namespace std;

// 抽象处理器类
class CHandler
{
public:
    CHandler() : m_pNext(NULL) {}

    void SetNext(CHandler* pHandler)
    {
        m_pNext = pHandler;
    }

    virtual void Handle(const string& strReq)
    {
        if (m_pNext != NULL)
        {
            m_pNext->Handle(strReq);
        }
    }

protected:
    CHandler* m_pNext;
};

// 部门经理处理类
class CDepartmentManager : public CHandler
{
public:
    void Handle(const string& strReq) override
    {
        cout << "Department Manager is reviewing the request" << endl;
        // 金额小于等于1000,由部门经理审批
        int nAmount = atoi(strReq.c_str());
        if (nAmount <= 1000)
        {
            cout << "Department Manager approved the request for $" << nAmount << endl;
        }
        else
        {
            cout << "Amount exceeds Department Manager's authority, passing to next level" << endl;
            // 调用基类方法,传递给下一个处理器
            CHandler::Handle(strReq);
        }
    }
};

// 财务经理处理类
class CFinanceManager : public CHandler
{
public:
    void Handle(const string& strReq) override
    {
        cout << "Finance Manager is reviewing the request" << endl;
        // 金额小于等于5000,由财务经理审批
        int nAmount = atoi(strReq.c_str());
        if (nAmount <= 5000)
        {
            cout << "Finance Manager approved the request for $" << nAmount << endl;
        }
        else
        {
            cout << "Amount exceeds Finance Manager's authority, passing to next level" << endl;
            // 调用基类方法,传递给下一个处理器
            CHandler::Handle(strReq);
        }
    }
};

// 高层管理人员处理类
class CCeo : public CHandler
{
public:
    void Handle(const string& strReq) override
    {
        cout << "CEO is reviewing the request" << endl;
        int nAmount = atoi(strReq.c_str());
        // 金额大于5000,由CEO审批
        if (nAmount > 5000)
        {
            cout << "CEO approved the request for $" << nAmount << endl;
        }
        else
        {
            cout << "Request should have been handled by lower levels" << endl;
        }
    }
};

int main()
{
    // 创建处理器对象
    CDepartmentManager deptManager;
    CFinanceManager financeManager;
    CCeo ceo;

    // 组装责任链
    deptManager.SetNext(&financeManager);
    financeManager.SetNext(&ceo);

    // 发送请求
    string requests[] = {"888", "3600", "9999"};
    for (const auto& strReq : requests)
    {
        cout << "Processing request for $" << strReq << ":" << endl;
        // 从责任链的起点开始处理
        deptManager.Handle(strReq);
        cout << endl;
    }

    return 0;
}

总结

        责任链模式有效解耦了发送者和接收者,发送请求的对象不需要知道哪个对象会处理请求。这减少了发送者与接收者之间的依赖,增强了系统的灵活性。责任链模式允许多个对象尝试处理一个请求,这一点特别适用于那些没有明确指定哪个对象应该处理特定类型的请求的情况,每个处理器都可以决定是否处理请求,或者将其传递下去。

        但如果责任链过长,可能会导致请求遍历整个链条才能找到合适的处理器,从而增加处理时间。在某些情况下,确保处理器按照正确的顺序处理请求可能是必要的。然而,责任链模式本身并不保证这一点,必须通过其他机制来实现。


http://www.kler.cn/a/540686.html

相关文章:

  • vcredist_x64.exe 是 Microsoft Visual C++ Redistributable 的 64 位版本
  • 非华为电脑制作一碰传NFC贴纸
  • BS架构(笔记整理)
  • C# 比较两个List集合内容是否相同
  • 理邦仪器嵌入式(C/C++开发)开发面试题及参考答案
  • 第433场周赛:变长子数组求和、最多 K 个元素的子序列的最值之和、粉刷房子 Ⅳ、最多 K 个元素的子数组的最值之和
  • 使用亚马逊针对 PyTorch 和 MinIO 的 S3 连接器进行模型检查点处理
  • php 实现 deepSeek聊天对话
  • MacOS安装Milvus向量数据库
  • 【AIGC】在VSCode中集成 DeepSeek(OPEN AI同理)
  • 蓝桥杯算法日记|贪心、双指针
  • 石英表与机械表的世纪之争(Quartz vs. Mechanical Watches):瑞士钟表业的危机与重生(中英双语)
  • 如何在Kickstart自动化安装完成后ISO内拷贝文件到新系统或者执行命令
  • 目标检测数据集合集(持续更新中)
  • centos docker安装
  • 【C#零基础从入门到精通】(八)——C#String字符串详解
  • 【华为OD-E卷 - 120 分割数组的最大差值 100分(python、java、c++、js、c)】
  • ABP框架9——自定义拦截器的实现与使用
  • 如何使用Socket编程在Python中实现实时聊天应用
  • 笔试-字符串2
  • Web前端开发--HTML
  • java后端开发day10--综合练习(一)
  • 基于“感知–规划–行动”的闭环系统架构
  • DeepSeek+3D视觉机器人应用场景、前景和简单设计思路
  • 深入理解TCP/IP协议栈:从原理到实践
  • Linux: ASoC 声卡硬件参数的设置过程简析