设计模式23-职责链

news2024/12/25 2:33:17

设计模式23-职责链

  • 动机
  • 定义与结构
    • 定义
    • 结构
      • 职责链模式
      • 图中元素解释
      • 工作流程
  • C++ 代码推导
  • 优缺点
  • 应用场景
  • 总结

动机

  • 在软件构建过程中,一个请求可能被多个对象处理。但是每个请求在运行时只能有一个接受者。如果显示指定将必不可少的带来请求发送者与接受者的紧耦合。
  • 那么如何使请求的发送者不需要指定具体的接受者?让请求的接受者自己的在运行时决定来处理请求,从而使两者解耦合。
  • 在许多情况下,多个对象可以处理某个请求,但具体由哪个对象来处理则取决于运行时的状态。职责链模式的动机是解耦请求的发送者和接受者,使多个对象都有机会处理这个请求。请求沿着一个由处理对象构成的链传递,直到有一个对象处理它为止。这种模式的好处是可以动态地改变处理链,并且可以通过增加或减少处理对象来灵活地应对变化。

定义与结构

定义

职责链模式(Chain of Responsibility Pattern)是一种行为设计模式,允许多个对象有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有对象处理它为止。

结构

在这里插入图片描述

这张结构图展示了设计模式中的职责链模式(Chain of Responsibility Pattern),但描述中有一处小误会,即Client类并不直接继承自Handler类,而是Client类依赖于一个Handler类型的对象。这里我们详细解释一下这个模式的结构和工作原理。

职责链模式

职责链模式是一种行为设计模式,它允许你将请求的发送者和接收者解耦,通过定义一个处理请求的接口来创建一系列的处理者,然后将它们连接成一条链。当接收到一个请求时,这个请求会沿着链传递,直到链中的某个处理者能够处理这个请求为止。

图中元素解释

  • Client:客户端角色,它创建了一个处理者链,并向链的第一个处理者对象提交请求。客户端通常不会自己处理请求,也不会知道链的结构。

  • Handler(处理者):这是一个抽象类或接口,声明了处理请求的接口,即HandleRequest()方法。它通常包含一个指向另一个处理者的引用(如后继处理者successor),如果这个处理者不能处理该请求,它会把请求转发给后继者。

  • ConcreteHandler1ConcreteHandler2:具体处理者角色,实现了抽象处理者(Handler)中所声明的处理请求的方法。具体处理者接收到请求后,可以处理它,也可以将请求传递给链中的下一个具体处理者。在图中,ConcreteHandler2是ConcreteHandler1的子类,这意味着它继承了ConcreteHandler1的所有行为,并且可以进一步特化或覆盖某些行为。

  • HandleRequest():处理请求的方法,它定义在Handler接口中,并由ConcreteHandler1和ConcreteHandler2具体实现。这个方法通常包含一些逻辑,用于判断这个处理者是否能够处理该请求。如果不能处理,则调用后继处理者的HandleRequest()方法。

  • successor:这个属性表示在处理者链中当前处理者的后继者。它用于在无法处理请求时将请求传递给链中的下一个处理者。

工作流程

  1. 客户端创建一个处理者链,并设置它们的后继者。
  2. 客户端向链的第一个处理者发送请求。
  3. 处理者检查自己是否能够处理该请求。
    • 如果可以,它就处理它。
    • 如果不可以,它就将请求转发给它的后继者,由后继者继续处理。
  4. 这个过程会一直持续下去,直到找到能够处理请求的处理者,或者处理者链结束(即没有后继者)。

这种设计模式的好处包括增加新的处理者变得更加容易,只需要将其加入到链中即可;同时,请求的发送者和接收者解耦,提高了系统的灵活性和可扩展性。

C++ 代码推导

以下是使用职责链模式的一个示例,在这个例子中,我们创建了一个责任链来处理客户请求。每个具体处理者决定是否处理请求,如果不能处理则将请求传递给下一个处理者。

#include <iostream>
#include <memory>

// 抽象处理者
class Handler {
public:
    virtual ~Handler() = default;
    void setNext(std::shared_ptr<Handler> next) {
        this->nextHandler = next;
    }
    
    void handleRequest(int request) {
        if (this->canHandle(request)) {
            this->handle(request);
        } else if (nextHandler) {
            nextHandler->handleRequest(request);
        } else {
            std::cout << "No handler available for request " << request << std::endl;
        }
    }

protected:
    virtual bool canHandle(int request) = 0;
    virtual void handle(int request) = 0;

private:
    std::shared_ptr<Handler> nextHandler = nullptr;
};

// 具体处理者A
class ConcreteHandlerA : public Handler {
protected:
    bool canHandle(int request) override {
        return request < 10;
    }
    
    void handle(int request) override {
        std::cout << "ConcreteHandlerA handled request " << request << std::endl;
    }
};

// 具体处理者B
class ConcreteHandlerB : public Handler {
protected:
    bool canHandle(int request) override {
        return request >= 10 && request < 20;
    }
    
    void handle(int request) override {
        std::cout << "ConcreteHandlerB handled request " << request << std::endl;
    }
};

// 具体处理者C
class ConcreteHandlerC : public Handler {
protected:
    bool canHandle(int request) override {
        return request >= 20;
    }
    
    void handle(int request) override {
        std::cout << "ConcreteHandlerC handled request " << request << std::endl;
    }
};

int main() {
    // 创建处理者对象
    auto handlerA = std::make_shared<ConcreteHandlerA>();
    auto handlerB = std::make_shared<ConcreteHandlerB>();
    auto handlerC = std::make_shared<ConcreteHandlerC>();

    // 设置责任链
    handlerA->setNext(handlerB);
    handlerB->setNext(handlerC);

    // 客户端发出请求
    int requests[] = {5, 15, 25, 30};
    for (int request : requests) {
        handlerA->handleRequest(request);
    }

    return 0;
}

优缺点

优点

  1. 降低耦合度:请求的发送者和接收者解耦,发送者无需了解处理者的具体信息。
  2. 责任链灵活:通过改变链内的成员或调整链的顺序,允许动态地增加或删除责任链上的处理者。
  3. 分离关注点:每个处理者只关注自己能处理的请求,其他请求会传递给下一个处理者。

缺点

  1. 不保证被处理:如果没有处理者处理该请求,则请求可能会丢失。
  2. 性能开销:如果链条太长,可能导致请求的处理速度变慢,影响系统性能。
  3. 调试困难:由于请求会沿着链条传递,调试时可能需要逐步跟踪请求通过链条的每一步。

应用场景

职责链模式常用于以下场景:

  1. 多个对象可以处理同一请求,但具体由哪个对象处理由运行时决定
  2. 需要动态地指定处理者。例如日志处理系统中,可以将不同级别的日志处理器串联起来,根据日志的级别来决定处理的处理器。
  3. 需要在处理者间解耦,例如事件分发系统、审批流程等。

职责链模式在许多系统中都是一种非常有用的设计模式,特别是在需要灵活配置请求处理逻辑的场景下。

总结

  • 责任链模式对应用场合在于一个请求可能有多个接受者。但是最后真正的接受者只有一个,这时候请求发送者与接受者的耦合有可能出现变化脆弱的症状。这次练的目的就是将二者进行解耦。从而更好地应对变化。
  • 应用了责任链模式后,对象的职责分配将更加灵活我们可以在运行时动态添加或者修改请求的处理职责。
  • 如果请求传递到职责链的末尾仍得不到处理,应该有一个合理的缺省机制。这也是每一个接受对象的责任,而不是发出请求的对象的责任。

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

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

相关文章

lvs+keepalive大战haproxy+keepalive实现高可用集群

华子目录 lvskeepalive实验架构实验前的准备工作1.主机准备2.KA1和KA2上安装lvskeepalive3.webserver1和webserver2上安装httpd4.制作测试效果网页内容5.所有主机关闭firewalld和selinux6.开启httpd服务 实验步骤1.webserver1和webserver2上配置vip2.webserver1和webserver2上关…

【C语言】 作用域和存储期

C语言的作用域和存储期 一、作用域1、概念&#xff1a;2、函数声明作用域3、局部作用域4、全局作用域5、作用域的临时掩盖6、static关键字 二、存储期1、概念2、自动存储期3、静态存储期4、自定义存储期 一、作用域 1、概念&#xff1a; \quad C语言中&#xff0c;标识符都有一…

《小迪安全》学习笔记03

须知少时凌云志&#xff0c;曾许人间第一流。 静态页面&#xff08;HTML&#xff09;是没有漏洞的&#xff0c;没有数据传递。 动态网站一般来说&#xff0c;有开发组合&#xff0c;即开发语言和数据库&#xff0c;两者兼容性比较好&#xff1a; 而且有的数据库不支持windows或…

网站自动化锚文本的实现逻辑

锚文本&#xff0c;‌即超链接的文本部分&#xff0c;‌它在网页中扮演着至关重要的角色。‌通过点击锚文本&#xff0c;‌用户可以方便地在网页间进行跳转&#xff0c;‌从而极大地提升了用户体验。‌同时&#xff0c;‌在搜索引擎优化&#xff08;‌SEO&#xff09;‌领域&am…

idea 修改背景图片教程

&#x1f30f;个人博客主页&#xff1a;意疏-CSDN博客 希望文章能够给到初学的你一些启发&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏支持一下笔者吧&#xff5e; 阅读指南&#xff1a; 开篇说明修改背景图片 开篇说明 给小白看得懂的修改图片教程&…

Spring项目:文字花园(三)

一.实现博客详情 1.后端逻辑代码 controller层添加方法&#xff08;根据博客id查看博客详情&#xff09; RequestMapping("/getBlogDetail")public Result<BlogInfo> getBlogDetail(Integer blogId){log.info("getBlogDetail, blogId: {}", blogId…

并发编程 | Future是如何优化程序性能

在初识Future一文中介绍了Future的核心方法。本文中接着介绍如何用Future优化我们的程序性能。 在此之前&#xff0c;有必要介绍Future接口的一个实现类FutureTask。 FutureTask介绍 FutureTask继承结构 首先我们看一下FutureTask的继承结构&#xff1a; public class Futur…

JUC阻塞队列(二):LinkedBlockingQueue

1、LinkedBlockingQueue 介绍 LinkedBlockingQueue 也是接口BlockingQueue的一个实现类&#xff0c;与 ArrrayBlockingQueue基于 数组实现不同的是&#xff0c;LinkedBlockingQueue是基于单项链表实现的&#xff0c;在LinkedBlockingQueue 内部维护了一个单向链表来存储数据&am…

探索深度学习的力量:从人工智能到计算机视觉的未来科技革命

目录 1. 引言 2. 人工智能的历史背景 3. 深度学习的崛起 3.1 深度神经网络的基本原理 4. 计算机视觉的发展现状 4.1 传统计算机视觉与深度学习的结合 5. 深度学习在计算机视觉中的应用 5.1 图像分类 5.2 目标检测 6. 深度学习引领的未来科技创新与变革 7. 结论 引言…

opencv cv.findContours 函数图像轮廓层级(记录)

opencv cv.findContours 函数详解 图像轮廓层级 图像轮廓检索方式 cv.findContours contours, hierarchy cv.findContours( image, mode, method[, contours[, hierarchy[, offset]]] ) 参数1&#xff1a;源图像 参数2&#xff1a;轮廓的检索方式&#xff0c;主要参数 参数3…

专题--自底向上的计算机网络(物理层)

目录 计算机网络概述 物理层 数据链路层 网络层 运输层 应用层 网络安全 详细见http://t.csdnimg.cn/MY5aI http://t.csdnimg.cn/8Ipa4 http://t.csdnimg.cn/uvMxS

康耐视相机与发那科机器人通过Ethernet I/P直连与程序编写

配置TCP/IP&#xff1a;按MENU—SETUP—NEXT—HOSTCOMM&#xff0c;选择TCP/IP—按ENTER或者F3[DETAIL] Port#1 IP addr&#xff1a;输入机器人IP地址&#xff0c;按ENTER后输入&#xff0c;如192.168.1.11&#xff1b;如果控制柜有2个网络端口&#xff0c;则按F3[PORT]进行切换…

科创中心“核”动力|趋动科技:AI算力界的领跑者

近日&#xff0c;趋动科技与深信服正式推出联合解决方案。联合解决方案将深信服EDS的高性能存储与趋动科技OrionX AI算力资源池化软件、以及GeminiAI训练平台有机结合&#xff0c;整合存力与算力资源的同时&#xff0c;帮助用户建好AI平台、管好AI资源、用好AI服务。 双方已完成…

监控zabbix的安装与使用

文章目录 1.zabbix的安装步骤2.zabbix的主动模式和被动模式简介及实现3.zabbix proxy主动及被动4.自定义监控&#xff0c;监控linux和连接状态&#xff0c;创建email进行基础报警5.部署zabbix agent脚本&#xff0c;适配rocky和ubuntu系统6.使用脚本&#xff0c;基于zabbix api…

yolov8旋转框+关键点检测

一、Yolov8obb_kpt -----------------------------------现已在v8官方库上更新旋转框分割算法和旋转框关键点检测算法-------------------------- ------------------------------------------- https://github.com/yzqxy/ultralytics-obb_segment---------------------------…

每天五分钟深度学习框架pytorch:自动求导机制

本文重点 深度学习框架pytorch拥有自动求导的机制,自动求导是 PyTorch 中非常重要的特性,能够让我们避免手动去计算非常复杂的导数,这能够极大地减少了我们构建模型的时间。本文学习的是第10步反向传播,学习路线参考前面一篇文章。 pytorch0.4版本 在pytorch的0.4版本中…

YOLO知识点总结:

分类&#xff1a; 即是将图像结构化为某一类别的信息&#xff0c;用事先确定好的类别(category)或实例ID来描述图片。这一任务是最简单、最基础的图像理解任务&#xff0c;也是深度学习模型最先取得突破和实现大规模应用的任务。其中&#xff0c;ImageNet是最权威的评测集&…

C语言刷题日记(附详解)(1)

一、选择判断部分 第一题&#xff1a; 如下代码是否存在风险&#xff0c;并说明原因和修改方案 #include<stdio.h> int main() {char* str "hello world";*str a;return 0; }思路提示&#xff1a;这种形式的字符串存储在什么区域呢&#xff1f;是否真的有…

【个人笔记公司项目】vue项目配置代理解决跨域问题

前后端分离模式势必会遇到跨域问题&#xff0c;比如我是10.106.46.169:8080要去请求10.114.46.108:9191。下面讲下代理详细步骤。 本文步骤基于本人的项目结构 一般项目结构已支持代理 // 部署时需要将改开关置为false window.isDev trueif (window.isDev) { // Devwindow.l…

计算机网络速成(二)

计算机网络面试&#xff08;二&#xff09;-CSDN博客 OSI七层体系架构 OSI七层模型是什么&#xff1f;每层的功能是什么&#xff1f; OSI七层模型是国际标准化组织&#xff08;ISO&#xff09;制定的一个用于计算机或通信系统间互联的标准体系&#xff0c;它从上到下分别是&am…