设置模式之责任链模式

news/2024/5/19 13:01:30 标签: 责任链模式, 设计模式, c++

目录

1.概述

2.结构

3.实现

4.总结


1.概述

责任链模式(Chain of Responsibility Pattern)是一种行为性设计模式;它为请求创建了一个接收者对象的链,允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。这种处理方法类似包与包之间的调用的思路,只是其可以不在主程序中累赘的去申明一堆if else变量使得程序更加臃肿。在我的博客C++之多层 if-else-if 结构优化(二)_c++ 怎么优化很多if 的代码呢-CSDN博客

中就是利用责任链模式来消除多层if-else-if。

2.结构

        责任链模式的重点是在“ 上,由一条链去处理相似的请求在链中决定谁来处理这个请 求,并返回相应的结果,其通用类图如下图 所示:

角色定义:

抽象处理者(Handler)定义一个处理请求的接口,通常包含一个处理请求的方法(如 handleRequest)和一个指向下一个处理者的引用(后继者),一般这类情况class内部都是纯虚函数。

具体处理者(ConcreteHandler)实现了抽象处理者接口,负责处理请求。如果能够处理该请求,则直接处理;否则,将请求传递给下一个处理者;这样可以通过设计整个逻辑链避免混乱。

客户端(Client)创建处理者对象,并将它们连接成一条责任链。通常,客户端只需要将请求发送给责任链的第一个处理者,无需关心请求的具体处理过程。

3.实现

以公司的请假为例,普通员工请假小于等于2天只需要自己的组长同意,请假大于2天小于等于5天需要部门经理同意,大于5天小于10天需要公司总经理同意才行,大于10天的请不了。根据上面的需求,我们可以先抽象Handler,再定义组长、部门经理、总经理,代码如下:

#include <iostream>
using namespace std;

//抽象处理者
class Handler
{
public:
    explicit Handler() { m_pNextHandler = NULL; }
    virtual ~Handler() {}

    //设置下一个处理者
    void setNextHandler(Handler *successor) { m_pNextHandler = successor; }

    //处理请求
    virtual void HandleRequest(int days) = 0;
protected:
    Handler *m_pNextHandler;  // 后继者
};


//组长
class CGroupLeader : public Handler
{
public:
    //处理请求
    void HandleRequest(int days) override
    {
        if (days <= 2)
        {
            cout << "我是组长,有权批准" << days << "天假,同意了!" << endl; 
        }
        else
        {
            m_pNextHandler->HandleRequest(days);
        }
    }
};

//部门经理
class CDeptManager : public Handler
{
public:
    //处理请求
    void HandleRequest(int days)  override
    {
        if (days <= 5)
        {
            cout << "我是部门经理,有权批准" << days << "天的假,同意了!" << endl;
        }
        else
        {
            m_pNextHandler->HandleRequest(days);
        }
    }
};

//总经理
class  CGeneralManager : public Handler
{
public:
    //处理请求
    void HandleRequest(int days) override
    {
        if (days <= 10)
        {
            cout << "我是总经理,最多让你请10天假,同意了!" << endl;
        }
        else
        {
            cout << "你请的假时间太长了,不同意!" << endl;
        }
    }
};

测试用例:

#include <memory>

int main()
{
    std::unique_ptr<Handler> pGroupLeader = new CGroupLeader;
    std::unique_ptr<Handler> pDeptLeader = new CDeptManager;
    std::unique_ptr<Handler> pGeneralManager = new CGeneralManager;

    //设置责任链
    pGroupLeader->setNextHandler(pDeptLeader.get());
    pDeptLeader->setNextHandler(pGeneralManager.get());

    pGroupLeader->HandleRequest(1);
    pGroupLeader->HandleRequest(2);
    pGroupLeader->HandleRequest(5);
    pGroupLeader->HandleRequest(8);
    pGroupLeader->HandleRequest(12);
    return 0;
}

输出:

我是组长,有权批准1天假,同意了!
我是组长,有权批准2天假,同意了!
我是部门经理,有权批准5天的假,同意了!
我是总经理,最多让你请10天假,同意了!
你请的假时间太长了,不同意!

4.总结

优点:

1) 解耦责任链模式将请求的发送者和接收者解耦,请求的发送者不需要知道接收者是谁,也不需要创建接收者的实例。同时,接收者也不需要知道请求的具体内容,只需要按照自已的业务逻辑进行相应的处理。这种解耦方式使得系统更加灵活,降低了耦合度,方便进行模块化开发和测试。
2) 链式处理:责任链模式可以形成一个处理链,请求在这个链中传递,每个节点都会对请求进行处理,这种方式可以实现复杂的业务逻辑,提高系统的可扩展性和可维护性。
3) 动态添加节点:在运行时,可以通过动态添加或册除节点来改变处理链,从而实现动态地扩展或修改处理逻辑。这种动态性使得系统更加灵活,能够适应不同的需求变化。


缺点:
1) 错误传播:在责任链模式中,如果某个节点处理请求时出现了错误,这个错误会沿看处理链向上传播,可能会导致整个链路崩溃。为了解决这个问题,需要确保每个节点都进行了错误处理,能够在出现错误时进行适当的处理或回退操作。
2) 无法终止链路:在某些情况下,如果请求不满足某个节点的条件,该节点就不需要对请求进行处理,但责任链模式无法直接终止链路。为了解决这人问题,可以在节点中添加判断逻辑,当请求不满足条件时直接返可或者进行其他处理。
3) 性能问题:由于请求会在多个节点间传递,因此责任链模式的性能可能会受到影响。特别是在请求量较大或处理逻辑较复杂的情况下,这种影响会更加明显。为了解决这个问题,可以对节点进行优化,提高处理效率,同时也可以考虑使用缓存等方式来降低请求的重复处理。
4) 节点之间的依频关条:在责任链模式中节点之间存在依赖关系,如果桌个节点的处理逻辑发生了变化,可能会影响到其他节点。这种依频关系可能会导致系统复杂度增加,增加了维护的难度。为了避免这种情况,可以尽量减少节点之间的依赖关系,使每个节点都尽可能独立地处理请
求。同时也可以采用模块化设计等方式来降低系统复杂度。


http://www.niftyadmin.cn/n/5345933.html

相关文章

arcgis实现截图/截屏功能

arcgis实现截图/截屏功能 文章目录 arcgis实现截图/截屏功能前言效果展示相关代码 前言 本篇将使用arcgis实现截图/截屏功能&#xff0c;类似于qq截图 效果展示 相关代码 <!DOCTYPE html> <html> <head><meta charset"utf-8"><meta nam…

周订单量超300%增长!百度智能云千帆AI原生应用商店公布百天成绩单

​ 1月25日&#xff0c;国内首家面向企业客户进行一站式交易的AI原生应用商店——百度智能云千帆AI原生应用商店上线100天。上线百日&#xff0c;累计上线AI原生应用超100款&#xff0c;涵盖文案智能创作、AI作画、代码生成、数字人等应用场景&#xff0c;应用数量指数级增长…

GPT 如何不挂VPN使用

1、下载 Home | Tampermonkey 将下载的文件tampermonkey_stable.crx 拖到上面的扩展程序里面 2、登录Greasy Fork - 安全、实用的用户脚本大全 搜索自己想要使用的东西&#xff0c;如GPT 找到 CHAT网页增强了 点击按安装&#xff0c;然后打开使用方法里面的 网址就可以使用

【Linux C | 进程】进程间通信 | 信号 (带C语言例子,8352字详细讲解)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

java 利用gdal,将gdb中图层转为postgresql的表

文章目录 简要说明maven依赖样例代码 简要说明 在java开发中&#xff0c;将gdb的图层数据转为postgresql的空间表 maven依赖 <!--需要安装完gdal后&#xff0c;本地install gdal包才能使用 --><!--gdal安装可参考 https://blog.csdn.net/qq_41613913/article/detail…

【深度学习】CodeFormer训练过程,如何训练人脸修复模型CodeFormer

文章目录 BasicSR介绍环境数据阶段 I - VQGAN阶段 II - CodeFormer (w0)阶段 III - CodeFormer (w1) 代码地址&#xff1a;https://github.com/sczhou/CodeFormer/releases/tag/v0.1.0 论文的一些简略介绍&#xff1a; https://qq742971636.blog.csdn.net/article/details/134…

食品加工厂可视化视频AI智能监管方案,助力工厂数字化运营

一、背景与需求分析 随着科技的不断进步和人们对食品安全和质量的日益关注&#xff0c;食品智慧工厂的建设成为了食品行业的一个重要趋势。智能化的食品工厂可以利用先进的技术和自动化系统&#xff0c;提高生产效率、降低监管成本&#xff0c;并确保产品的质量和安全。 行业…

多符号表达式的共同子表达式提取教程

生成的符号表达式&#xff0c;可能会存在过于冗长的问题&#xff0c;且多个符号表达式中&#xff0c;有可能存在相同的计算部分&#xff0c;如果不进行处理&#xff0c;计算过程中会导致某些算式计算多次&#xff0c;从而影响计算效率。 那么多个符号表达式生成函数时&#xf…