C++软件设计模式之责任链模式

news2025/1/4 19:18:13

责任链模式的动机与意图

动机:
在软件开发中,经常会遇到需要处理一系列请求或事件的情况。这些请求可能需要经过多个处理对象,每个对象根据其职责决定是否处理请求或将其传递给下一个对象。责任链模式(Chain of Responsibility Pattern)提供了一种将请求的发送者和接收者解耦的方式,允许多个对象都有机会处理请求,从而避免了请求发送者与接收者之间的紧密耦合。

意图:
责任链模式的意图是使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合。将这些对象连成一条链,并沿着这条链传递请求,直到有对象处理它为止。

适用场合

  1. 多个对象可以处理同一请求,但具体由哪个对象处理在运行时确定。
  2. 需要在不明确指定接收者的情况下,向多个对象中的一个提交请求。
  3. 需要动态指定一组对象处理请求,例如在运行时动态调整处理链。

责任链模式的变体

  1. 纯责任链模式:

    • 每个处理者要么处理请求,要么将请求传递给下一个处理者,但不能同时进行。
    • 这种模式通常用于严格的链式处理,例如审批流程。
  2. 不纯责任链模式:

    • 处理者可以部分处理请求,然后将请求传递给下一个处理者。
    • 这种模式允许处理者在处理请求的同时,继续传递请求,适用于需要多个处理者共同完成任务的场景。
  3. 带中断的责任链模式:

    • 处理者可以在处理请求后决定是否中断链的传递。
    • 这种模式适用于某些情况下,一旦请求被处理,就不需要继续传递的场景。
  4. 带优先级的责任链模式:

    • 处理者根据优先级决定是否处理请求,优先级高的处理者先处理请求。
    • 这种模式适用于需要根据优先级决定处理顺序的场景。

以下是基于责任链模式的不同变体的 C++ 代码示例。每个示例都展示了如何在 C++ 中实现责任链模式的不同形式。


1. 纯责任链模式

在纯责任链模式中,每个处理者要么处理请求,要么将请求传递给下一个处理者。处理者不会同时处理请求并传递请求。

#include <iostream>
#include <memory>

class Handler {
public:
    virtual ~Handler() = default;
    virtual void setNext(std::shared_ptr<Handler>) = 0;
    virtual void handle(const std::string& request) = 0;
};

class BaseHandler : public Handler {
protected:
    std::shared_ptr<Handler> nextHandler;

public:
    void setNext(std::shared_ptr<Handler> handler) override {
        nextHandler = handler;
    }

    void handle(const std::string& request) override {
        if (nextHandler) {
            nextHandler->handle(request);
        }
    }
};

class ConcreteHandlerA : public BaseHandler {
public:
    void handle(const std::string& request) override {
        if (request == "A") {
            std::cout << "ConcreteHandlerA handles request: " << request << std::endl;
        } else {
            BaseHandler::handle(request);
        }
    }
};

class ConcreteHandlerB : public BaseHandler {
public:
    void handle(const std::string& request) override {
        if (request == "B") {
            std::cout << "ConcreteHandlerB handles request: " << request << std::endl;
        } else {
            BaseHandler::handle(request);
        }
    }
};

int main() {
    auto handlerA = std::make_shared<ConcreteHandlerA>();
    auto handlerB = std::make_shared<ConcreteHandlerB>();

    handlerA->setNext(handlerB);

    handlerA->handle("B");  // ConcreteHandlerB handles request: B
    handlerA->handle("A");  // ConcreteHandlerA handles request: A
    handlerA->handle("C");  // No handler can process C

    return 0;
}


2. 不纯责任链模式

在不纯责任链模式中,处理者可以部分处理请求,然后将请求传递给下一个处理者。

#include <iostream>
#include <memory>

class Handler {
public:
    virtual ~Handler() = default;
    virtual void setNext(std::shared_ptr<Handler>) = 0;
    virtual void handle(const std::string& request) = 0;
};

class BaseHandler : public Handler {
protected:
    std::shared_ptr<Handler> nextHandler;

public:
    void setNext(std::shared_ptr<Handler> handler) override {
        nextHandler = handler;
    }

    void handle(const std::string& request) override {
        if (nextHandler) {
            nextHandler->handle(request);
        }
    }
};

class ConcreteHandlerA : public BaseHandler {
public:
    void handle(const std::string& request) override {
        if (request == "A") {
            std::cout << "ConcreteHandlerA handles request: " << request << std::endl;
        } else {
            std::cout << "ConcreteHandlerA partially processes request: " << request << std::endl;
            BaseHandler::handle(request);
        }
    }
};

class ConcreteHandlerB : public BaseHandler {
public:
    void handle(const std::string& request) override {
        if (request == "B") {
            std::cout << "ConcreteHandlerB handles request: " << request << std::endl;
        } else {
            std::cout << "ConcreteHandlerB partially processes request: " << request << std::endl;
            BaseHandler::handle(request);
        }
    }
};

int main() {
    auto handlerA = std::make_shared<ConcreteHandlerA>();
    auto handlerB = std::make_shared<ConcreteHandlerB>();

    handlerA->setNext(handlerB);

    handlerA->handle("B");  // ConcreteHandlerB handles request: B
    handlerA->handle("A");  // ConcreteHandlerA handles request: A
    handlerA->handle("C");  // ConcreteHandlerA partially processes request: C
                             // ConcreteHandlerB partially processes request: C

    return 0;
}


3. 带中断的责任链模式

在带中断的责任链模式中,处理者可以在处理请求后决定是否中断链的传递。

#include <iostream>
#include <memory>

class Handler {
public:
    virtual ~Handler() = default;
    virtual void setNext(std::shared_ptr<Handler>) = 0;
    virtual bool handle(const std::string& request) = 0;
};

class BaseHandler : public Handler {
protected:
    std::shared_ptr<Handler> nextHandler;

public:
    void setNext(std::shared_ptr<Handler> handler) override {
        nextHandler = handler;
    }

    bool handle(const std::string& request) override {
        if (nextHandler) {
            return nextHandler->handle(request);
        }
        return false;
    }
};

class ConcreteHandlerA : public BaseHandler {
public:
    bool handle(const std::string& request) override {
        if (request == "A") {
            std::cout << "ConcreteHandlerA handles request: " << request << std::endl;
            return true;  // 中断链式传递
        }
        return BaseHandler::handle(request);
    }
};

class ConcreteHandlerB : public BaseHandler {
public:
    bool handle(const std::string& request) override {
        if (request == "B") {
            std::cout << "ConcreteHandlerB handles request: " << request << std::endl;
            return true;  // 中断链式传递
        }
        return BaseHandler::handle(request);
    }
};

int main() {
    auto handlerA = std::make_shared<ConcreteHandlerA>();
    auto handlerB = std::make_shared<ConcreteHandlerB>();

    handlerA->setNext(handlerB);

    handlerA->handle("B");  // ConcreteHandlerB handles request: B
    handlerA->handle("A");  // ConcreteHandlerA handles request: A
    handlerA->handle("C");  // No handler can process C

    return 0;
}


4. 带优先级的责任链模式

在带优先级的责任链模式中,处理者根据优先级决定是否处理请求,优先级高的处理者先处理请求。

#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>

class Handler {
public:
    virtual ~Handler() = default;
    virtual int getPriority() const = 0;
    virtual void handle(const std::string& request) = 0;
};

class BaseHandler : public Handler {
protected:
    int priority;

public:
    BaseHandler(int p) : priority(p) {}

    int getPriority() const override {
        return priority;
    }

    void handle(const std::string& request) override {
        // 默认不处理
    }
};

class ConcreteHandlerA : public BaseHandler {
public:
    ConcreteHandlerA(int p) : BaseHandler(p) {}

    void handle(const std::string& request) override {
        if (request == "A") {
            std::cout << "ConcreteHandlerA handles request: " << request << std::endl;
        }
    }
};

class ConcreteHandlerB : public BaseHandler {
public:
    ConcreteHandlerB(int p) : BaseHandler(p) {}

    void handle(const std::string& request) override {
        if (request == "B") {
            std::cout << "ConcreteHandlerB handles request: " << request << std::endl;
        }
    }
};

int main() {
    auto handlerA = std::make_shared<ConcreteHandlerA>(2);
    auto handlerB = std::make_shared<ConcreteHandlerB>(1);

    std::vector<std::shared_ptr<Handler>> handlers = {handlerA, handlerB};

    // 根据优先级排序
    std::sort(handlers.begin(), handlers.end(), [](const auto& h1, const auto& h2) {
        return h1->getPriority() > h2->getPriority();
    });

    for (const auto& handler : handlers) {
        handler->handle("B");  // ConcreteHandlerB handles request: B
        handler->handle("A");  // ConcreteHandlerA handles request: A
    }

    return 0;
}


总结

以上代码示例展示了责任链模式的四种不同变体:

  1. 纯责任链模式:处理者要么处理请求,要么传递请求。
  2. 不纯责任链模式:处理者可以部分处理请求并传递请求。
  3. 带中断的责任链模式:处理者可以中断链的传递。
  4. 带优先级的责任链模式:处理者根据优先级决定处理顺序。

这些变体可以根据具体需求灵活选择和实现,以满足不同场景下的功能需求。

基于责任链模式特点的软件架构模式

  1. 中间件架构:

    • 在Web开发中,中间件架构通常使用责任链模式来处理HTTP请求。每个中间件都可以对请求进行处理,然后决定是否将请求传递给下一个中间件。
    • 例如,Express.js中的中间件机制就是基于责任链模式实现的。
  2. 事件处理系统:

    • 在GUI编程中,事件处理系统通常使用责任链模式来处理用户事件。每个事件处理器可以处理事件,或者将事件传递给下一个处理器。
    • 例如,Java AWT/Swing中的事件处理机制就是基于责任链模式实现的。
  3. 工作流引擎:

    • 在工作流引擎中,责任链模式可以用于处理工作流中的各个步骤。每个步骤可以处理任务,或者将任务传递给下一个步骤。
    • 例如,Activiti等工作流引擎中的任务处理机制就是基于责任链模式实现的。
  4. 过滤器链:

    • 在Web应用中,过滤器链通常使用责任链模式来处理请求和响应。每个过滤器可以对请求或响应进行处理,然后将其传递给下一个过滤器。
    • 例如,Java Servlet中的过滤器机制就是基于责任链模式实现的。

总结

责任链模式通过将请求的发送者和接收者解耦,提供了一种灵活的方式来处理请求。它适用于多个对象可以处理同一请求的场景,并且可以通过不同的变体来满足不同的需求。基于责任链模式的特点,许多软件架构模式(如中间件架构、事件处理系统、工作流引擎和过滤器链)都采用了这种模式来实现灵活的处理机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2270179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈电力监控系统在厂房电力工程中的设计与应用

安科瑞汪洋/汪小姐/汪女士---Acrelwy 摘要 &#xff1a;电力监控系统在厂房电力工程中的应用&#xff0c;稳步提升了电力系统管理的智能化、信息化水平&#xff0c;确保电力资源的合理化应用&#xff0c;满足工业生产的基本需求。为确保电力监控系统与厂房电力工程的有效结合&…

AIGC生图实战技巧分享

目录 引言 &#x1f343;安装与配置代码 &#x1f343;数据处理代码 &#x1f343;生图请求代码 引言 本文展示了 AIGC 生图相关的代码示例&#xff0c;包括安装与配置、数据处理以及生图请求等不同阶段的代码&#xff0c;清晰呈现了整个技术实现过程中代码层面的操作要点和…

Mac iTerm2集成DeepSeek AI

1. 去deepseek官网申请api key&#xff0c;DeepSeek 2. 安装iTerm2 AI Plugin插件&#xff0c;https://iterm2.com/ai-plugin.html&#xff0c;插件解压后直接放到和iTerms相同的位置&#xff0c;默认就在/Applications 下 3. 配置iTerm2 4. 重启iTerm2,使用快捷键呼出AI对话…

akamai3.0反爬教程逆向分析9个视频汇总

目录 一、akamai2.0文章二、akamai3.0每月疑似改版点二、9个视频汇总如下 一、akamai2.0文章 文章1cookie反爬之akamai_2.0-上文章2cookie反爬之akamai_2.0-上文章3cookie反爬之akamai_2.0-上文章中akamai2.0对应调试html与js文件 二、akamai3.0每月疑似改版点 详细文字与2.…

解决chatgpt(mac app登陆)出现报错:获取您的 SSO 信息时出错

由于我们是app登陆的&#xff0c;不能直接修改网站的链接&#xff0c;将 URL 的域名部分从 auth.openai.com 变更为 auth0.openai.com&#xff0c;然后加载新的地址&#xff0c;这时候应该就可以正常登录或注册了。 所以我们使用邮箱先载入auth0的地址&#xff0c;再更改自己的…

基于Springboot + vue实现的高校办公室行政事务管理系统

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

UE5通过蓝图节点控制材质参数

通过蓝图节点控制材质的参数 蓝图节点 在材质上设置标量值 和 在材质上设置向量参数值 Set Scalar Parameter Value on Materials Set Vector Parameter Value on Materials 这两个蓝图节点都可以在蓝图中&#xff0c;控制材质的参数值和向量值

DeepSeek-VL2

《DeepSeek-VL2: Mixture-of-Experts Vision-Language Models for Advanced Multimodal Understanding》是 DeepSeek-AI 团队发布的关于视觉语言模型 DeepSeek-VL2 的论文&#xff0c;以下是对该论文的详细介绍&#xff1a; 研究背景与动机 多模态理解的重要性&#xff1a;在当…

【第二部分--Python之基础】03 容器类型的数据

Python内置的数据类型如序列&#xff08;列表、元组等&#xff09;、集合和字典等可以容纳多项数据&#xff0c;我们称它们为容器类型的数据。 序列 序列&#xff08;sequence&#xff09;是一种可迭代的、元素有序的容器类型的数据。 序列包括列表&#xff08;list&#xff…

大型概念模型:在句子表示空间中的语言建模

《Large Concept Models: Language Modeling in a Sentence Representation Space》这篇论文介绍了一种新的语言模型方法&#xff0c;它在句子表示空间中进行建模。该方法旨在改进传统语言模型的局限性&#xff0c;通过捕捉更高级别的语义信息来提高自然语言处理任务的表现。 模…

日期时间选择(设置禁用状态)

目录 1.element文档需要 2.禁用所有过去的时间 3.设置指定日期的禁用时间 <template><div class"block"><span class"demonstration">起始日期时刻为 12:00:00</span><el-date-pickerv-model"value1"type"dat…

Mac 安装Mysql启动Mysql以及数据库的常规操作

Mac 安装Mysql启动Mysql以及数据库的常规操作 一、mysql的安装 1、登录官方网站:dev.mysql.com/downloads/mysql/ 二、查看系统架构 uname -m 在MAC中&#xff1a; 如果输出结果是 x86_64&#xff0c;则表示你的系统是 x86-64 架构。 如果输出结果是 arm64&#xff0c;则表示…

2011-2020年各省粗离婚率数据

2011-2020年各省粗离婚率数据 1、时间&#xff1a;2011-2020年 2、来源&#xff1a;国家统计局 3、指标&#xff1a;地区、年份、粗离婚率 4、范围&#xff1a;31省 5、指标解释&#xff1a;粗离婚率指某地区当年离婚对数占该地区年平均人口的比重。计算公式为&#xff1a…

【Cocos TypeScript 零基础 2.1】

目录 cocos常识新建动画添加组件 cocos 下载就不讲了,多的很 cocos 界面设置中文 新建一个2D项目 SIKI_学院_点击跳转 常识 竖屏 宽720 高1280 如果背景图确定是竖屏也可以根据背景图片大小来确定项目宽高 鼠标功能 左键 选中 滚轮 放大缩小 右键 移动视角位置 场景 双击…

UE蓝图战利品掉落动画

战利品掉落动画&#xff0c;其实就是添加个冲量 add impulse 什么是冲量&#xff1f; 冲量 &#xff08;impulse&#xff09;是作用在物体上的力 在 时间上的累积效果

Transformer从零详细解读——DASOU讲AI

1. 从全局角度概括Transformer transformer的任务是什么&#xff1f; 进一步细化 进一步细化&#xff0c;注意&#xff1a;每个encoder结构相同&#xff0c;参数不同&#xff1b;decoder同理 原论文中的图如下&#xff1a; 2.Encoder 2.1 输入部分 &#xff08;1&#xff09…

(四)配置有线网口、SSH登陆、文件传输以及运行交叉编译程序测试

文章目录 配置有线网口原因自动分配不行第一步 设置前先停止网络接口第二步 手动分配ip第三步 使配置的网口ip永久生效第四步 测试一下网络是否通了 SSH登陆文件传输以及运行交叉编译程序测试第一种借助基于SSH的命令行工具SCP传输文件第二种借助基于MobaXterm 软件直接上传测试…

欧美短剧系统出海:小体量撬动大市场

近年来&#xff0c;出海短剧在欧美市场掀起了一阵热潮&#xff0c;成为了全球娱乐产业中一颗冉冉升起的新星。 欧美短剧凭啥爆火&#xff1f; 精准把握碎片化娱乐需求 现代欧美社会生活节奏飞快&#xff0c;人们的时间愈发碎片化。出海短剧每集约 3 分钟的时长&#xff0c;完…

折旧后将成本中心折旧费调整到订单中

背景&#xff1a;设备原作为通用设备&#xff0c;按成本中心折旧&#xff0c;在12月月结正常折旧后才明确为专用设备&#xff0c;需要按内部订单折旧。 问&#xff1a;折旧能不能冲销。 回复&#xff1a; 在SAP中&#xff0c;折旧凭证是无法直接冲销的。如果折旧计提有误&#…

前端CSS3学习

学习菜鸟教程 火狐-moz- 谷歌 Safari -webkit- 前面都加这个&#xff0c;可能才生效 边框 border: 1px solid #ddd 粗细 样式 样色 经常和border-radius 一块用 border-radius: 50px 20px 第一个左右 第二个右左 border-top-left-radius … box-shadow: 10px 5px 10px 0 #88…