不得不说的行为型模式-责任链模式

news2024/11/28 14:53:54

目录

责任链模式: 

 

底层原理:

代码案例:

下面是面试中可能遇到的问题:


责任链模式: 

责任链模式是一种行为型设计模式,它允许多个对象在一个请求序列中依次处理该请求,直到其中一个对象能够处理它为止。这些对象被组织成一条链,并且每个对象都有一个指向下一个对象的引用。

 

底层原理:

  • 客户端将请求发送到责任链中的第一个对象。
  • 如果该对象能够处理请求,则处理请求并返回结果。
  • 如果该对象不能处理请求,则将请求传递给下一个对象。
  • 重复此过程,直到找到能够处理请求的对象或责任链末尾。

代码案例:

下面是一个简单的 C++ 代码案例,以说明责任链模式的实现方式。假设我们正在处理一个简单的文本编辑器,需要实现一系列文本处理器来处理不同的文本格式。我们可以使用责任链模式来处理这些请求,以便让每个处理器能够处理它们自己能够处理的请求。

在上面的代码中,我们定义了一个 TextProcessor 接口,其中包含了一个 process 方法,它接受一个字符串作为输入,并将其处理。然后,我们定义了三个具体的文本处理器:PlainTextProcessorHtmlTextProcessorMarkdownProcessor。这些处理器都实现了 TextProcessor 接口,并且能够处理不同类型的文本格式。

HtmlTextProcessorMarkdownProcessor 都有一个指向下一个处理器的指针,这样它们就可以将请求传递给下一个处理器。在每个处理器的 process 方法中,它会检查输入的文本是否符合该处理器所能处理的格式。如果是,它就处理该文本;否则,它就将该文本传递给下一个处理器,直到找到能够处理该文本的处理器为止。

main 函数中,我们定义了一个责任链,将 PlainTextProcessorHtmlTextProcessorMarkdownProcessor 链接在一起。然后,我们向该链中的第一个处理器发送三个不同的文本请求。第一个请求是普通文本,第二个请求是 HTML 格式的文本,第三个请求是 Markdown 格式的文本。我们可以看到,在每个请求中,只有能够处理该请求的处理器才会处理该请求,而其他处理器则将其传递给下一个处理器。

该代码的输出如下所示:

PlainTextProcessor: This is some plain text.
HtmlTextProcessor: <html><body><h1>This is an HTML document.</h1></body></html>
MarkdownProcessor: This is some **markdown** text.

可以看到,在第一个请求中,只有 PlainTextProcessor 能够处理该请求,因此它处理了该请求。在第二个请求中,只有 HtmlTextProcessor 能够处理该请求,因此它处理了该请求。在第三个请求中,只有 MarkdownProcessor 能够处理该请求,因此它处理了该请求。

这个例子展示了责任链模式的基本实现方式。责任链模式可以帮助我们实现解耦和灵活性,因为它允许我们在运行时动态地组合和分离对象。

下面是面试中可能遇到的问题:

  1. 什么是责任链模式?它有什么作用?

  2. 在责任链模式中,处理器之间的连接是怎样的?怎样才能保证处理器按照正确的顺序被调用?

  3. 责任链模式中的处理器都有哪些角色?它们是如何协同工作的?

  4. 责任链模式有哪些优点和缺点?你能够举例说明吗?

可以先自己思考一下,看参考答案是不是和你想的一样哦=v=~

可能的答案如下:

缺点:

  1. 责任链模式是一种行为型模式,它允许我们将多个处理器链接在一起,形成一个处理器链。当一个请求从链的一端进入时,处理器链会依次尝试处理该请求,直到找到能够处理该请求的处理器为止。责任链模式的作用是解耦请求发送者和接收者之间的关系,使系统更加灵活。

  2. 在责任链模式中,处理器之间的连接是一条链式结构。每个处理器都有一个指向下一个处理器的指针。为了保证处理器按照正确的顺序被调用,需要将处理器按照一定的顺序链接在一起。一般来说,这个顺序应该是从最具体的处理器开始,依次向上层抽象处理器链接。当请求进入责任链时,它会从链的第一个处理器开始,依次向下传递,直到找到能够处理该请求的处理器为止。

  3. 在责任链模式中,处理器一般分为两种角色:具体处理器和抽象处理器。具体处理器是责任链中最底层的处理器,它们负责处理请求,并决定是否将请求传递给下一个处理器。抽象处理器是一个接口或抽象类,它定义了处理器的共同接口,并保存了下一个处理器的指针。在链中的任何一个处理器都可以通过它的接口来发送请求,并将请求传递给下一个处理器。

  4. 责任链模式的优点包括:可以动态地组合和分离对象;可以使系统更加灵活;可以避免将请求发送者和接收者之间的关系硬编码在一起。其缺点包括:由于每个请求都要在责任链中传递,因此可能会对性能产生一定的影响;在处理器链过长或者没有正确设置链中处理器的顺序时,可能会导致请求不能被正确处理。例如,一个简单的应用场景是文本处理,不同的文本处理器可以根据文本

    的类型和需求被组合成一个处理器链,实现文本处理的功能。

    一个可能的C++代码案例如下:

    #include <iostream>
    #include <string>
    
    // 抽象处理器
    class Handler {
    public:
        Handler(Handler* successor) : successor_(successor) {}
        virtual ~Handler() {}
    
        // 处理请求的虚函数
        virtual void handleRequest(const std::string& request) {
            if (successor_) {
                successor_->handleRequest(request);
            }
        }
    
    protected:
        Handler* successor_;
    };
    
    // 具体处理器 A
    class ConcreteHandlerA : public Handler {
    public:
        ConcreteHandlerA(Handler* successor) : Handler(successor) {}
    
        virtual void handleRequest(const std::string& request) override {
            if (request == "A") {
                std::cout << "ConcreteHandlerA handles the request." << std::endl;
            }
            else {
                Handler::handleRequest(request);
            }
        }
    };
    
    // 具体处理器 B
    class ConcreteHandlerB : public Handler {
    public:
        ConcreteHandlerB(Handler* successor) : Handler(successor) {}
    
        virtual void handleRequest(const std::string& request) override {
            if (request == "B") {
                std::cout << "ConcreteHandlerB handles the request." << std::endl;
            }
            else {
                Handler::handleRequest(request);
            }
        }
    };
    
    // 具体处理器 C
    class ConcreteHandlerC : public Handler {
    public:
        ConcreteHandlerC(Handler* successor) : Handler(successor) {}
    
        virtual void handleRequest(const std::string& request) override {
            if (request == "C") {
                std::cout << "ConcreteHandlerC handles the request." << std::endl;
            }
            else {
                Handler::handleRequest(request);
            }
        }
    };
    
    // 客户端代码
    int main() {
        ConcreteHandlerA handlerA(nullptr);
        ConcreteHandlerB handlerB(&handlerA);
        ConcreteHandlerC handlerC(&handlerB);
    
        // 将请求依次发送给责任链的第一个处理器
        handlerC.handleRequest("A");
        handlerC.handleRequest("B");
        handlerC.handleRequest("C");
        handlerC.handleRequest("D");
    
        return 0;
    }
    

    在这个代码案例中,Handler 是抽象处理器,定义了所有处理器都应该有的接口。具体处理器 ConcreteHandlerAConcreteHandlerBConcreteHandlerC 继承了 Handler 接口,并实现了各自的处理逻辑。

    在客户端代码中,首先创建了三个具体处理器,并将它们依次链接在一起,形成一个处理器链。然后将请求依次发送给责任链的第一个处理器,让处理器链依次尝试处理该请求。

    当请求为 A 时,ConcreteHandlerA 可以处理该请求,因此它会输出相应的处理信息。当请求为 B 时,ConcreteHandlerB 可以处理该请求,因此它会输出相应的处理信息。当请求为 C 时,ConcreteHandlerC 可以处理该请求,因此它会输出相应的处理信息。当请求为 D 时,处理器链上的任何一个处理器都不能处理该请求,因此它不会输出任何处理信息

    5责任链模式的优缺点如下:

    优点:

  5. 将请求的发送者和接收者解耦。请求发送者无需知道哪个接收者能够处理该请求,接收者也无需知道请求的发送者是谁,以及该请求是从哪个接收者发出的。

  6. 可以动态的添加或删除处理器,因此责任链模式具有很好的灵活性和可扩展性。

  7. 由于请求可能需要经过多个处理器才能被处理,因此责任链模式的处理过程可能会比较缓慢。

  8. 对于长的责任链,请求可能会遍历整个责任链才能被处理,这可能会带来一些性能问题。

  9. 对于一些请求,如果没有任何一个处理器能够处理该请求,那么该请求就会被“吞掉”,导致该请求无法得到处理。

    • 责任链模式可以使得系统更加符合单一职责原则。每个具体处理器只负责处理与自己相关的请求,从而将复杂的业务逻辑拆分成多个小的处理器,让每个处理器聚焦于自己的领域,更加清晰明了。

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

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

相关文章

【VM服务管家】VM4.0平台SDK_2.5 全局工具类

目录 2.5.1 全局相机&#xff1a;全局相机设置参数的方法2.5.2 全局相机&#xff1a;获取全局相机列表的方法2.5.3 全局通信&#xff1a;通信管理中设备开启状态管理2.5.4 全局通信&#xff1a;接收和发送数据的方法2.5.5 全局变量获取和设置全局变量的方法 2.5.1 全局相机&…

经典重装上阵,更好用的中小手游戏鼠标,雷柏V300W上手

日常办公、玩游戏都需要用到鼠标&#xff0c;特别是对于游戏玩家来说&#xff0c;一款手感好、易定制的鼠标&#xff0c;绝对是游戏上分的利器。早先雷柏出过一款V300鼠标&#xff0c;距今已有10年历史&#xff0c;当时是很受欢迎&#xff0c;最近南卡又出了一款复刻版的V300W&…

为什么不要相信AI机器人提供的健康信息?

自从OpenAI、微软和谷歌推出了AI聊天机器人&#xff0c;许多人开始尝试一种新的互联网搜索方式&#xff1a;与一个模型进行对话&#xff0c;而它从整个网络上学到的知识。 专家表示&#xff0c;鉴于之前我们倾向于通过搜索引擎查询健康问题&#xff0c;我们也不可避免地会向Ch…

linux下的权限管理

1.shell概念 当我们在进入正文前先给大家普及一些基础概念。 广义上来讲&#xff0c;linux 发行版 linux内核 外壳程序&#xff08;这个外壳程序就相当于 windows gui&#xff08;窗口图形&#xff09;&#xff0c;linux 常用的shell 是 bash&#xff09; 所以&#xff0c…

vue基本语法

目录 一、模板语法 &#xff08;1&#xff09;文本 &#xff08;2&#xff09;原始HTML &#xff08;3&#xff09;属性Attribute &#xff08;4&#xff09;使用JavaScript表达式 二、条件渲染 &#xff08;1&#xff09;v-if&#xff0c;v-else &#xff08;2&#x…

nodejs+vue+elementui学生毕业生离校系统

学生毕业离校系统的开发过程中。该学生毕业离校系统包括管理员、学生和教师。其主要功能包括管理员&#xff1a;首页、个人中心、学生管理、教师管理、离校信息管理、费用结算管理、论文审核管理、管理员管理、留言板管理、系统管理等&#xff0c;前台首页&#xff1b;首页、离…

stm32 CubeMx 实现SD卡/sd nand FATFS读写测试

stm32 CubeMx 实现SD卡/SD nand FATFS读写测试 文章目录 stm32 CubeMx 实现SD卡/SD nand FATFS读写测试1. 前言2. 环境介绍2.1 软硬件说明2.2 外设原理图 3. 工程搭建3.1 CubeMx 配置3.2 SDIO时钟配置说明3.2 读写测试3.2.1 添加读写测试代码 3.3 FATFS文件操作3.3.1 修改读写测…

云计算:数字化转型的利器

随着数字化转型的加速&#xff0c;企业对于信息技术应用的需求越来越大&#xff0c;而云计算作为一种新的基础设施&#xff0c;也逐渐成为了许多企业的首选。那么&#xff0c;云计算究竟有哪些优势&#xff1f;未来发展趋势又是怎样的呢&#xff1f;下面就让我们一起来探讨一下…

深入理解try...catch(字节码层面)

我们工作中常用try...catch来解决程序中出现的异常情况&#xff0c;但是你真的了解它的实现原理吗&#xff1f;今天我就带着大家从字节码层面理解try...catch 一、准备工作 我们首先需要准备好异常类和对应的测试类方便我们观察。 异常类&#xff1a; public class DivideB…

1.软件测试

目录 一、面试重点 1.什么是软件测试&#xff1f; 2.软件测试和软件开发的区别 3.你为什么选择软件测试&#xff1f; 4.什么是需求&#xff1f; 5.软件测试人员如何深入了解需求&#xff1f; 6.什么是内存泄露&#xff1f; 7.什么是测试用例&#xff1f; 8.测试用例有…

【23】linux进阶——linux的软链接和硬链接

大家好&#xff0c;这里是天亮之前ict&#xff0c;本人网络工程大三在读小学生&#xff0c;拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识&#xff0c;希望能提高自己的技术的同时&#xff0c;也可以帮助到大家 另外其它专栏请关注&#xff1a; 锐捷数通实验&…

终于成功了,CCED2000后,中文编程软件再次脱颖而出,系出金山

WPS抗衡微软&#xff0c;CCEDE却被淹没&#xff1f; DOS代&#xff0c;我们用WPS来进行文字编辑&#xff0c;CCED来做表格&#xff0c;两者在那个时代可以称得上是国产办公领域的“必装软件”。 如今&#xff0c;30年过去了&#xff0c;WPS一步一步成长为抗衡微软office的国产…

electron入门 | 手把手带electron项目初始化

Electron是一个基于Chromium和 Node.js&#xff0c;可以使用 HTML、CSS和JavaScript构建跨平台应用的技术框架&#xff0c;兼容 Mac、Windows 和 Linux。 目录 1.了解electron 2.开发环境 3.初始化 采坑插曲&#xff1a; 1.了解electron Electron 可以让你使用纯 JavaScrip…

easyexcel读取excel合并单元格数据

普通的excel列表&#xff0c;easyexcel读取是没有什么问题的。但是&#xff0c;如果有合并单元格&#xff0c;那么它读取的时候&#xff0c;能获取数据&#xff0c;但是数据是不完整的。如下所示的单元格数据&#xff1a; 我们通过简单的异步读取&#xff0c;最后查看数据内容&…

symfonos 2

目录 扫描 SMB SSH 提权 扫描 由于端口80是打开的,我们试图在浏览器中打开IP地址,但在网页上没有找到任何有用的信息。我们还尝试了dirb和其他目录暴力工具,但没有找到任何东西。 SMB 为了进一步枚举,我们使用Enum4Linux工具并找到了一些有用的信息。我们发现了一个名…

Microelectronic学习章节总结(1)-- 计算机架构复习

文章目录 Part1. 处理器架构&#xff0c;以及流水线的实现方法part2 DLX架构part3 ULTRA SPARC T2架构part4 PENTIUM 4架构part5 不同架构之间的性能比较 PPT&#xff1a;2&#xff0c;4&#xff0c;5&#xff0c;6 这一章主要对之前的计算机架构一些知识进行复习&#xff0c;因…

数字中国建设峰会|大模型带来产业智能化新机遇

第六届数字中国建设峰会在福建省福州市举办。峰会期间&#xff0c;百度与福州市政府签署战略协议&#xff0c;将基于文心一言为代表的大模型和百度智能云通用AI能力深入合作。未来&#xff0c;双方将聚焦算力产业&#xff0c;共建百度智能云&#xff08;福州&#xff09;智算中…

移动推车定位查找方案

CK_Label_v24 产品型号 CK_Label_v24 尺寸 124x90x12mm&#xff08;不含安装支架&#xff09; 屏幕尺寸 4.2 inch 显示技术 电子墨水屏显示 显示区域面积 (mm) 84.8(H) x 63.6(V) 分辨率 400*300 像素密度 120dpi 显示颜色 黑/白 外观颜色 白色&灰外圏…

Mozilla 自身是如何模糊 Firefox 浏览器的?

导语&#xff1a;Mozilla一直在模糊Firefox及其底层组件&#xff0c;它已被证明是识别质量和安全漏洞的最有效方法之一。 Mozilla一直在模糊Firefox及其底层组件&#xff0c;它已被证明是识别质量和安全漏洞的最有效方法之一。通常&#xff0c;研究人员会在不同级别上应用模糊测…

二叉树的遍历及相关衍生

二叉树的遍历及相关衍生 前言二叉树的遍历建树二叉树的遍历遍历的分类代码部分 遍历根的应用打印树中的每个数据代码部分 遍历计算树节点个数代码部分 计算二叉树的深度思路代码部分 第k层个数 结束 前言 如标题所示&#xff0c;在这里我们要研究的是二叉树的遍历。 为什么不…