C++设计模式——Chain of Responsibility职责链模式

news/2025/1/21 21:13:14/

一,职责链模式的定义

职责链模式,又被称为责任链模式,是一种行为型设计模式,它让多个对象依次处理收到的请求,直到处理完成为止。

职责链模式需要使用多个对象,其中的每个对象要么处理请求,要么将请求传递给下一个对象,该模式因此可以实现发送方与接收方的松散耦合。

在职责链模式中,一个对象可以被理解为处理器,每个处理器都包含对下一个处理器的引用,多个对象之间形成了一个链表的结构。

职责链模式在现实生活中的抽象实例:

审批流程:在流程中,当一个申请需要多级审批时,可以使用职责链模式。每一级审批者都是职责链的一部分。

银行账户验证:在银行系统中,需要对用户进行身份验证和授权操作,而验证操作涉及多个步骤。

异常处理:在程序开发中,每个异常处理器可以处理特定类型的异常,如果当前处理器无法解决,则传递给下一个处理器。

二,职责链模式的结构

职责链模式主要包含以下组件:

1.抽象处理器(Handler):

处理器的抽象类,声明处理请求的抽象接口,并持有对下一个处理器的引用。

2.具体处理器(ConcreteHandler):

继承自抽象处理器,包含了对处理请求接口的具体实现,负责处理特定类型的请求或将请求传递给下一个处理器。

3.客户端(Client):

负责创建处理器的实例,并将它们加入到职责链中。然后向第一个处理器发送请求,并等待职责链的返回结果。

组件之间的工作步骤如下:

1.客户端将请求传递给职责链中的第一个处理器。

2.第一个处理器尝试处理请求。如果处理成功,则结束处理过程并返回结果,如果无法处理,则将请求转发给下一个处理器。

3.下一个处理器重复步骤2,直到找到能够处理请求的处理器,或者职责链中没有更多的处理器。

4.客户端获得处理结果。

对应UML类图:

三,职责链模式代码样例

#include <iostream>
#include <string>
class Handler
{
protected:Handler* successor;
public:void setSuccessor(Handler* successor){this->successor = successor;}virtual void handleRequest(const std::string& request) = 0;
};
class ConcreteHandler1 : public Handler
{
public:void handleRequest(const std::string& request) override{if (request == "Type1"){std::cout << "Handling request of type Type1." << std::endl;}else if (successor != nullptr){successor->handleRequest(request);}else{std::cout << "Unable to handle the request." << std::endl;}}
};
class ConcreteHandler2 : public Handler
{
public:void handleRequest(const std::string& request) override{if (request == "Type2"){std::cout << "Handling request of type Type2." << std::endl;}else if (successor != nullptr){successor->handleRequest(request);}else{std::cout << "Unable to handle the request." << std::endl;}}
};
class ConcreteHandler3 : public Handler
{
public:void handleRequest(const std::string& request) override{if (request == "Type3"){std::cout << "Handling request of type Type3." << std::endl;}else if (successor != nullptr){successor->handleRequest(request);}else{std::cout << "Unable to handle the request." << std::endl;}}
};
int main()
{Handler* handler1 = new ConcreteHandler1();Handler* handler2 = new ConcreteHandler2();Handler* handler3 = new ConcreteHandler3();handler1->setSuccessor(handler2);handler2->setSuccessor(handler3);handler1->handleRequest("Type2");handler1->handleRequest("Type3");handler1->handleRequest("Type4");delete handler1;delete handler2;delete handler3;return 0;
}

运行结果:

Handling request of type Type2.
Handling request of type Type3.
Unable to handle the request.

四,职责链模式的应用场景

命令处理器:比如在游戏或GUI应用中,用户可以发送各种操作命令,如“播放音乐”、“关闭窗口”,而具体执行过程由一系列处理器完成。

日志记录器:将不同严重等级的日志交给不同的处理器去打印。

Web服务开发:在Web服务中,对请求进行校验和过滤,如权限验证、数据校验等。

权限控制:在用户权限管理中,可以根据角色的不同职责分配不同的权限验证步骤。

消息路由:在网络通信中,将不同类型的消息分别发送给不同的处理程序。

五,职责链模式的优缺点

职责链模式的优点:

和命令模式类似,可以实现发送者和接收者的解耦。

灵活性强,可以修改职责链中的结构和顺序。

有扩展性,可以在最小改动的情况下添加新的处理器。

处理器可以在不同的职责链中重复使用。

职责链模式的缺点:

对请求的处理可能覆盖不全,导致bug的产生。

请求的处理过程十分冗长。

请求的传递涉及多个对象,性能开销大。

责任链需要被一直维护和管理。

六,代码实战

Demo1:日志记录器

#include <iostream>
#include <string>
#include <vector>
//Logger接口
class Logger {
public:virtual void log(const std::string& message) = 0;
};
//处理正常日志
class InfoLogger: public Logger{
public:void log(const std::string& message) override {std::cerr << "Info: " << message << std::endl;}
};
//处理调试日志
class DebugLogger: public Logger{
public:void log(const std::string& message) override {std::cout << "Debug: " << message << std::endl;}
};
//处理错误日志
class ErrorLogger: public Logger{
public:void log(const std::string& message) override {std::cerr << "Error: " << message << std::endl;}
};
class LoggingChain {
private:std::vector<std::shared_ptr<Logger>> loggers;
public:void addLogger(std::shared_ptr<Logger> logger) {loggers.push_back(logger);}void log(const std::string& message) {for (auto it = loggers.rbegin(); it != loggers.rend(); ++it) {(*it)->log(message);}}
};
int main() {LoggingChain chain;chain.addLogger(std::make_shared<InfoLogger>());chain.addLogger(std::make_shared<DebugLogger>());chain.addLogger(std::make_shared<ErrorLogger>());chain.log("This is a test message.");return 0;
}

运行结果:

Error: This is a test message.
Debug: This is a test message.
Info: This is a test message.

Demo2:模拟消息接收

#include <iostream>
#include <string>
#include <vector>
class Message {
public:virtual ~Message() {}
};
class TextMessage : public Message {
};
class ImageMessage : public Message {
};
class MessageHandler{
public:virtual void handle(Message* msg) = 0;
};
class TextProcessor: public MessageHandler{
public:void handle(Message* msg) override{if (dynamic_cast<TextMessage*>(msg)) {std::cout << "handling a text message." << std::endl;process(*static_cast<TextMessage*>(msg));}else {forward(msg);}}
private:void process(TextMessage& msg) {}void forward(Message* msg) {}
};
class ImageProcessor: public MessageHandler{
public:void handle(Message* msg) override {if (dynamic_cast<ImageMessage*>(msg)) {std::cout << "handling an image message." << std::endl;process(*static_cast<ImageMessage*>(msg));}else {forward(msg);}}
private:void process(ImageMessage& img){}void forward(Message* msg){}
};
class ChainOfResponsibility {
public:void setHandler(MessageHandler* handler){current_ = handler;}void handle(Message* msg) {current_->handle(msg);}
private:MessageHandler* current_ = nullptr;
};
int main() {ChainOfResponsibility chain;TextProcessor txtProc;ImageProcessor imgProc;chain.setHandler(&txtProc);chain.handle(new TextMessage());chain.setHandler(&imgProc);chain.handle(new ImageMessage());return 0;
}

运行结果:

handling a text message.
handling an image message.

七,参考阅读

https://www.geeksforgeeks.org/chain-responsibility-design-pattern/

https://www.tutorialspoint.com/design_pattern/chain_of_responsibility_pattern.htm

https://sourcemaking.com/design_patterns/chain_of_responsibility

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

相关文章

iPhone手机清理软件:照片清理功能全解析

在数字化生活中&#xff0c;智能手机成为我们记录生活点滴的主要工具&#xff0c;尤其是iPhone&#xff0c;以其卓越的相机功能备受用户青睐。然而&#xff0c;成千上万的照片迅速堆积&#xff0c;不仅占用了大量存储空间&#xff0c;还使得设备运行缓慢。在众多解决方案中&…

数据传输安全——混合加解密(国密)

国密SM2与SM4混合加密解密工具类详解及其与其他加密算法的对比分析 在当今互联网时代,信息安全变得尤为重要。随着国家密码局发布的商用密码算法(即国密算法)逐渐普及,SM2和SM4等算法因其高效性和安全性成为了国内应用中的重要组成部分。本文不仅将详细介绍一个基于Java的…

如何本地搭建Whisper语音识别模型

要在本地搭建Whisper语音识别模型&#xff0c;你需要遵循以下步骤&#xff0c;注意Whisper模型是由OpenAI发布的&#xff0c;但基于你的要求&#xff0c;这里将尽可能提供详细的指导&#xff1a; 环境准备&#xff1a; 首先&#xff0c;确保你的计算机安装了Python&#xff0c;…

SAM2POINT:以zero-shot且快速的方式将任何 3D 视频分割为视频

摘要 我们介绍 SAM2POINT&#xff0c;这是一种采用 Segment Anything Model 2 (SAM 2) 进行零样本和快速 3D 分割的初步探索。 SAM2POINT 将任何 3D 数据解释为一系列多向视频&#xff0c;并利用 SAM 2 进行 3D 空间分割&#xff0c;无需进一步训练或 2D-3D 投影。 我们的框架…

Mac(M2)系统手动安装ADB

ADB压缩包下载地址 下载解压后运行命令 zsh命令 // /Desktop/android为解压后文件夹的路径 ~ 符号表示跟目录1. echo export PATH$PATH:~/Desktop/android/platform-tools/ >> ~/.zshrc// 使第一步配置生效 2. source ~/.zshrc shell命令 // /Desktop/android为解…

计算机组成原理:总线技术深度解析

目录 1. 总线技术概述 1.1 什么是总线&#xff1f; 1.2 总线的基本功能 2. 总线的类型 2.1 内部总线 2.2 外部总线 3. 总线的标准与协议 3.1 常见的总线标准 3.2 总线协议 4. 总线的性能考量 4.1 带宽 4.2 延迟 4.3 可扩展性 5. 总线的未来趋势 6. 结语 在计算机…

VMware中共享文件夹没了怎么办?

1.进入root su root 需要提前设置密码 sudo passwd root 2.创建一个hgfs文件夹&#xff0c;share就在这里面 sudo mkdir /mnt/hgfs/ 3.输入下面的命令 sudo mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other 4.然后就能找到share文件夹了&#xff0c;注意每…

PDF读取表格写入EXCEL

声明&#xff1a;只记录&#xff0c;不推荐&#xff0c;因为e-iceblue的spire.pdf是收费的&#xff0c;要licence。 pom引入 <repositories><repository><id>com.e-iceblue</id><name>e-iceblue</name><url>https://repo.e-iceblu…