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

责任链模式的动机与意图

动机:
在软件开发中,经常会遇到需要处理一系列请求或事件的情况。这些请求可能需要经过多个处理对象,每个对象根据其职责决定是否处理请求或将其传递给下一个对象。责任链模式(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: BhandlerA->handle("A");  // ConcreteHandlerA handles request: AhandlerA->handle("C");  // No handler can process Creturn 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: BhandlerA->handle("A");  // ConcreteHandlerA handles request: AhandlerA->handle("C");  // ConcreteHandlerA partially processes request: C// ConcreteHandlerB partially processes request: Creturn 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: BhandlerA->handle("A");  // ConcreteHandlerA handles request: AhandlerA->handle("C");  // No handler can process Creturn 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: Bhandler->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.rhkb.cn/news/497605.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

部署SenseVoice

依赖 Conda cuda pythor 查看GPU版本-CSDN博客 创建虚拟conda环境 conda create --name deeplearn python3.10 conda activate deeplearn git clone https://github.com/FunAudioLLM/SenseVoice.git cd SenseVoice pip install -r requirements.txt pip install gradio pyth…

【Compose multiplatform教程06】用IDEA编译Compose Multiplatform常见问题

当我们从Kotlin Multiplatform Wizard | JetBrains 下载ComposeMultiplatform项目时 会遇到无法正常编译/运行的情况&#xff0c;一般网页和桌面是可以正常编译的&#xff0c; 我这里着重解决如下问题 1:Gradle版本不兼容或者Gradle连接超时 2:JDK版本不兼容 3:Gradle依赖库连…

yolov4算法及其改进

yolov4算法及其改进 1、yolov4介绍2、mosaic与mish激活函数2.1、mosaic数据增强2.2、Mish激活函数 3、backbone网络框架的改进4、PAN-FPN的介绍5、样本匹配和损失函数5.1、样本匹配5.2、YOLOV4损失函数5.2.1、GIOU loss5.2.2、DIOU loss5.2.3、CIOU Loss 1、yolov4介绍 改进点&…

Edge如何获得纯净的启动界面

启动Edge会出现快速链接&#xff0c;推广链接&#xff0c;网站导航&#xff0c;显示小组件&#xff0c;显示信息提要&#xff0c;背景 ●复杂页面 ●精简页面 点击页面设置按钮 关闭快速链接 关闭网站导航 关闭小组件 关闭信息提要 关闭背景 关闭天气提示 精简页面看起来十分舒…

目标检测文献阅读-YOLO:统一的实时目标检测(12.23-12.29)

目录 摘要 Abstract 1 引言 2 统一的检测 3 网络设计 4 训练 5 YOLOv5训练猫狗识别模型 5.1 项目代码整体结构介绍 5.2 数据集和预训练权重的准备 5.3 训练猫狗识别模型 5.3.1 修改数据配置文件 5.3.2 修改模型配置文件 5.3.3 训练模型 5.3.4 启用tensorbord查看…

要查询 `user` 表中 `we_chat_subscribe` 和 `we_chat_union_id` 列不为空的用户数量

文章目录 1、we_chat_subscribe2、we_chat_union_id 1、we_chat_subscribe 要查询 user 表中 we_chat_subscribe 列不为空的用户数量&#xff0c;你可以使用以下 SQL 查询语句&#xff1a; SELECT COUNT(*) FROM user WHERE we_chat_subscribe IS NOT NULL;解释&#xff1a; …

【模块系列】STM321.69TFT屏幕

前言 在翻翻自己的器件盒的时候&#xff0c;发现这块好久之前买的TFT屏了&#xff0c;想起还没有用STM32点亮过&#xff0c;手头上正好有立创的梁山派STM32F4&#xff0c;就试着按照网上的文章教程顺便移植个LVGL看看&#xff0c;然后就有了就本文。 代码工程命名的是LvglDemo&…

Unity中列表List使用出类似字典Dictionary的感觉

首先为什么会有这个标题&#xff1f; 因为字典很好用&#xff0c;只需要键就能拿到值&#xff0c;这种感觉是真的爽&#xff0c;新手最喜欢用了&#xff0c;遇事不决就字典&#xff0c;但是也有不好的地方&#xff0c;字典的内存开销比列表List要大&#xff0c;遍历也是List占…

Android中使用AIDL实现进程通信

前言 关于使用AIDL实现两个APP&#xff08;跨进程&#xff09;通信&#xff0c;我们通常把两个APP分别叫做服务端和客户端。本文不讲原理&#xff0c;只给最简易的案例。 一、服务端APP实现 1. 在src/main/aidl目录下新建一个.aidl文件&#xff0c;然后在.aidl文件中定义需要…

Mac安装多个版本node、java、python 等开发软件环境,安装、卸载、升级多个数据库

安装多个版本node、java、python 等开发软件环境 使用nvm&#xff08;Node.js Version Manager&#xff09;来管理多个Node.js版本。 使用jenv来管理多个Java版本。 使用pyenv来管理多个Python版本。 以下是安装和使用这些版本管理器的基本步骤&#xff1a; 1. 安装多个版本…

Ftrace: 深入探究Linux内核的追踪利器

文章目录 一、 前言二、Ftrace介绍2.1 Ftrace框架2.2 Ftrace的使用场景 三、Ftrace配置和控制接口四、Ftrace使用步骤1&#xff1a;配置内核2. 挂载debugfs3. 查看和配置Ftrace4. 开始追踪[可选]5. 查看追踪结果6. 保存追踪数据7. 清除追踪配置 五、实战演示5.1 function跟踪器…

人工智能基础软件-Jupyter Notebook

简介&#xff1a; Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算&#xff1a;开发、文档编写、运行代码和展示结果。 Jupyter Notebook是以网页的形式打开&#xff0c;可以在网页页面中直接编写代码和运行代码&#xff0c;代码的运行结果也会直…

tesla openday数据驱动串讲

一、我写的目的 tesla的数据驱动全流程代表着现在&#xff08;曾经&#xff09;的sota&#xff0c;总结和沉淀他的方法总结后与自己现在的理念做一次对标&#xff0c;查漏补缺找到自己现在的主要问题&#xff0c;聚焦下一阶段的投入 二、主要方法 本文不讲解tesla的视觉技术…

基于神经网络的车牌识别算法matlab仿真 人工智能方法 车牌识别

一 设计方法 设定matlab的车牌识别系统&#xff0c;用神经网络进行预测&#xff0c;将数据集划分为训练集和测试集&#xff0c;设计神经网络结构。根据输入特征的维度和输出标签的维度&#xff0c;确定网络层数和节点数。使用训练集对神经网络进行训练。通过迭代优化网络权重和…

计算机体系结构期末复习4:多处理器缓存一致性(cache一致性)

目录 一、cache一致性问题 1.一致性定义 2.问题定义 3.解决问题的基本策略 二、写返回(write-back)cache的一致性处理 1.MSI协议 2.MESI协议 3.MOESI协议 三、补充知识点&#xff1a;提升cache性能的因素 1.cache miss的三种情况&#xff1a; 2.影响cache性能的因素…

信息化时代的步伐

信息化时代的步伐 下载压缩包的&#xff0c;解压压缩包得到 这里给了一串数字 我们不知道要用什么解码就用随波逐流解码 一键解码得到 说明这是用中文电报解码&#xff1a; flag{计算机要从娃娃抓起}

Linux 基本指令

目录 1.常见指令 1.1 ls指令 1.2 pwd指令 1.3 cd指令 1.4 touch指令 1.5 mkdir指令 1.6 rm和rmdir指令 1.7 man指令 1.8 cp指令 1.9 mv指令 ​编辑 1.10 cat指令 1.11 more指令 1.12 less指令 1.13 head指令 1.14.tail指令 1.15 时间相关的指令 1.16 cal…

TCP客户端模拟链接websocket服务端发送消息(二)

兄弟们&#xff0c;我来填坑了&#xff0c;o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o&#xff0c;前几天写了个tcp模拟websocket客户端的以为完成&#xff0c;后面需要发送消息给服务端&#xff0c;以为简单不就是一个发送消息么&#xff0c;这不是一…