设计模式-责任链模式(Chain of Responsibility Pattern)结构|原理|优缺点|场景|示例

                                     设计模式(分类)        设计模式(六大原则)   

    创建型(5种)        工厂方法         抽象工厂模式        单例模式        建造者模式        原型模式

    结构型(7种)        适配器模式        装饰器模式        代理模式        ​​​​​​外观模式      桥接模式        组合模式       享元模式

    行为型(11种)      策略模式        模板方法模式        观察者模式        迭代器模式     责任链模式     命令模式    备忘录模式          状态模式          访问者模式        中介者模式    


责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它将请求的发送者与接收者解耦,让多个接收者对象形成一条链,并沿着这条链传递请求,直到有一个接收者处理它为止。每个接收者都有权决定是否处理请求,或者将请求转发给链上的下一个接收者。

结构:

  • Handler(处理者)接口/抽象类: 定义处理请求的接口,通常包含一个处理请求的方法(如 handleRequest()),以及一个设置或获取下一个处理者的方法(如 setNext() 和 getNext())。
  • ConcreteHandler(具体处理者): 实现处理者接口,负责处理特定类型的请求。每个具体处理者在处理请求时,可以选择处理请求、拒绝处理(通常通过返回特定值或抛出异常表示)或将其转发给下一个处理者。

原理: 

        请求发起者只需将请求发送给链上的第一个处理者,后续的传递过程完全由链上的处理者自行决定。每个处理者检查请求是否符合其处理条件,若符合则处理并终止传递,否则将请求转发给下一个处理者。这样,请求的发送者无需关心请求如何被处理,处理的责任分散在链上的各个处理者中。

优缺点:

  • 优点

    • 发送者与接收者解耦,增加系统的灵活性,易于扩展新的处理者或调整处理顺序。
    • 便于实现请求的分发、过滤、路由等功能。
    • 通过在链上动态地添加或删除处理者,可以改变系统的处理行为。
  • 缺点

    • 链条过长可能导致请求处理的效率下降。
    • 如果处理链的构造不合理,可能会导致请求得不到处理(例如,链中没有能够处理该请求的处理者)。
    • 调试较为困难,因为请求的处理过程可能涉及多个处理者。

场景:

  • 处理请求可能有多种方式或多种条件,需要在运行时动态确定。
  • 不希望请求发送者与接收者之间存在紧密耦合。
  • 需要对请求进行过滤、分发、路由等操作。

 代码示例(以Java为例)

在责任链模式中,决定下一个处理者的责任通常由处理者自身承担。具体而言,每个处理者在处理请求时,可以根据请求的内容、自身的处理能力等因素,判断是否需要将请求传递给链上的下一个处理者。下面是一个Java实现的例子,展示了处理者如何决定下一个处理者:

// 处理者接口
public abstract class Handler {protected Handler nextHandler;public void setNext(Handler handler) {this.nextHandler = handler;}public abstract void handleRequest(Request request);
}// 具体处理者A
public class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(Request request) {if (canHandle(request)) {// 处理请求...System.out.println("ConcreteHandlerA handled the request.");} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("No suitable handler found for the request.");}}private boolean canHandle(Request request) {// 根据请求内容判断处理者A是否能处理该请求// 这里仅作为示例,实际逻辑应根据业务需求实现return request.getType().equals("TypeA") && request.getPriority() >= 5;}
}// 具体处理者B
public class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(Request request) {if (canHandle(request)) {// 处理请求...System.out.println("ConcreteHandlerB handled the request.");} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("No suitable handler found for the request.");}}private boolean canHandle(Request request) {// 根据请求内容判断处理者B是否能处理该请求// 这里仅作为示例,实际逻辑应根据业务需求实现return request.getType().equals("TypeB") && request.getPriority() <= 8;}
}// 请求类
public class Request {private String type;private int priority;// ... 构造函数、getters、setters ...
}// 使用示例
public class Client {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNext(handlerB);  // 构建责任链Request requestA = new Request("TypeA", 7);  // 创建请求对象ARequest requestB = new Request("TypeB", 6);  // 创建请求对象BhandlerA.handleRequest(requestA);  // 发起请求AhandlerA.handleRequest(requestB);  // 发起请求B}
}

        在这个例子中,ConcreteHandlerA 和 ConcreteHandlerB 分别实现了 canHandle() 方法,用于判断是否能处理给定的请求。在 handleRequest() 方法中,每个处理者首先检查自己是否能处理请求,如果可以,则处理请求并终止传递;否则,将请求传递给下一个处理者。这种设计使得每个处理者都能根据请求内容自主决定是否处理或传递请求,从而实现了责任链模式的核心思想。

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

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

相关文章

对于C# 任务并行库(TPL)的一些理解

C# 的任务并行库&#xff08;Task Parallel Library&#xff0c;TPL&#xff09;是 .NET 框架的一个部分&#xff0c;它提供了一组丰富的API&#xff0c;旨在简化并行编程&#xff0c;使开发人员能够更容易地构建可以利用多核处理器优势的高性能应用程序。TPL 的设计目的是减少…

【redis】Redis数据类型(一)——String类型(包含redis通用命令)

目录 Redis通用命令String类型常用的操作命令一些特殊命令详解setnx示例使用 setrange示例 mset示例 msetnx示例 append示例 getset示例 incr示例使用1.计数器2.限速器 bitcount示例使用&#xff1a;使用 bitmap 实现用户上线次数统计性能 String类型String类型简介String类型的…

统一威胁情报如何赋能SOC应对复杂威胁?

安全运营中心&#xff08;SOC&#xff09;是组织网络安全战略的核心组成部分&#xff0c;扮演着至关重要的角色。其负责实时监控整个IT基础设施&#xff0c;以检测、响应和预防各类网络安全威胁。网络安全威胁日益复杂且多变的数字化时代&#xff0c;攻击平面泛化、基础设施复杂…

GET 和 POST 请求方式的区别

GET 和 POST 请求方式的区别 GET请求和POST请求在HTTP通信中有着不同的用途和限制。以下是两者之间的一些主要区别&#xff1a; URL可见性 GET请求的参数直接附加在URL后面&#xff0c;因此可以被用户看到POST请求的参数位于请求体中&#xff0c;对URL参数是不可见的 数据传输方…

C#技巧之窗体去鼠标化

简介 在窗体程序中不用鼠标&#xff0c;直接使用键盘完成想要的操作。 实现的方法有两种&#xff0c;一种是使用键盘上的Tab键使控件获得焦点&#xff0c;然后用enter键触发该控件上的事件&#xff08;一般为click事件&#xff09;。另一种是&#xff0c;为控件添加快捷键&am…

新手去做视频号小店常见的问题解答!全篇干货!建议收藏!

大家好&#xff0c;我是电商小V 视频号小店现在可以说是越来越火&#xff0c;在创业者的人群中被提及的次数也是越来越高&#xff0c;导致这种情况的原因就是&#xff0c;新项目&#xff0c;正处于红利期&#xff0c;现在去做是可以很轻易分到属于自己的一杯羹&#xff0c;就是…

Android 蓝牙无法发送或接收某些类型文件

Android 蓝牙应用使得用户能够在蓝牙设备之间进行文件传输。用户可以通过蓝牙连接两台设备&#xff0c;并在它们之间传输文件&#xff0c;如照片、音乐、视频等。这对于用户来说是非常便利的&#xff0c;无需使用数据线或互联网连接&#xff0c;可以直接在附近的设备之间进行文…

基于SpringBoot的“大学生社团活动平台”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“大学生社团活动平台”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统结构图 管理员登录界面图 管理员功能界…

C#基础|数组的使用、字符串的分隔与连接

哈喽,你好,我是雷工! 01 数组概念 数组是一个变量,用来存储“相同数据类型”的“一组数据”。 02 数组与普通变量的区别 声明一个变量,就是在内存空间分配一块儿合适的空间; 声明一个数组,就是在内存空间分配一串儿连续的空间。 03 数组基本要素 标识符:数组的名…

SpringCloud中网关-详解、案例(代码)

简介&#xff1a;在Spring Cloud中&#xff0c;网关的角色是非常重要的&#xff0c;它负责整个系统的入口流量&#xff0c;并且可以处理路由、过滤、协议转换等操作 目录 1、网关的技术实现 1.1 网关功能 1.2 网关的形式 2、网关实现步骤 2.1 添加相关依赖 2.2 创建此mod…

【算法刷题 | 贪心算法05】4.27(K次取反后最大化的数组和、加油站)

文章目录 8.K次取反后最大化的数组和8.1题目8.2解法&#xff1a;贪心8.2.1贪心思路8.2.2代码实现 9.加油站9.1题目9.2解法&#xff1a;贪心9.2.1贪心思路9.2.2代码实现 8.K次取反后最大化的数组和 8.1题目 给你一个整数数组 nums 和一个整数 k &#xff0c;按以下方法修改该数…

【深度学习-番外1】Win10系统搭建VSCode+Anaconda+Pytorch+CUDA深度学习环境和框架全过程

专栏的老读者们都知道&#xff0c;以前的文章以使用MATLAB的为多。 不过后续陆续开始展开深度学习算法的应用&#xff0c;就会逐渐引入Python语言了&#xff08;当然MATLAB的代码也会同步更新&#xff09;&#xff0c;这是由于在深度学习领域&#xff0c;Python应用更为广泛。…

6.比较含退格的字符串(力扣字符串)(两种解法:字符串操作,栈)

目录 题目链接 法一&#xff1a;普通字符串操作 法二&#xff1a;栈操作 题目链接 . - 力扣&#xff08;LeetCode&#xff09; 法一&#xff1a;普通字符串操作 用len1记录目前s的字符个数&#xff0c;len2记录目前t的字符个数 如果不是#&#xff0c;则s[len1] s[i] 如果是…

解决Android Studio安卓开发写入文件问题

有很多小伙伴想把文件写进安卓系统储存失败&#xff0c;类似下面的代码 val file File("account.txt")val writer BufferedWriter(FileWriter(file))writer.use {it.write(username "," password)} 用java方式写入读出文件但是显示成功但是找不到文件…

Linux--自主编写shell

目录 准备知识 shell原理 shell与用户互动的过程 实现shell 0.用到的头文件和宏定义 1.首先我们需要自己输出一个命令行 2.获取用户命令行字符 3.命令行字符串分割 4.执行命令 5.设置循环 6.检测内建命令 7.完善细节--获取工作目录而非路径 准备知识 Linux--环境…

Linux系统安全与应用【二】

目录 1.开关机安全控制 1.2 实例&#xff1a;GRUB 菜单设置密码 2.终端登录安全控制 2.1 限制root只在安全终端登录 ​3.弱口令检测 3.1 Joth the Ripper,JR​编辑 4.网络端口扫描 4.1 nmap命令 1.开关机安全控制 1.1 GRUB限制 限制更改GRUB引导参数 通常情况下在系统…

类和对象【三】析构函数和拷贝构造函数

文章目录 析构函数析构函数的定义析构函数的作用主要作用次要作用 析构函数的特点 拷贝构造函数拷贝构造函数的定义拷贝构造函数的作用主要作用次要作用 拷贝构造函数的特点浅拷贝和深拷贝浅拷贝深拷贝 拷贝构造函数的调用场景 析构函数 析构函数的定义 析构函数(destructor) …

mybatis基本使用

文章目录 1. mybatis2. 基本使用(1) maven坐标(2) 配置文件编写(3) 数据库操作(4) 注解查询 2. 基本配置(1) 读取外部配置文件(2) mapper映射 3. 映射文件查询删除/修改/新增 动态sql 1. mybatis MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高…

使用 Gradio 的“热重载”模式快速开发 AI 应用

在这篇文章中&#xff0c;我将展示如何利用 Gradio 的热重载模式快速构建一个功能齐全的 AI 应用。但在进入正题之前&#xff0c;让我们先了解一下什么是重载模式以及 Gradio 为什么要采用自定义的自动重载逻辑。如果你已熟悉 Gradio 并急于开始构建&#xff0c;请直接跳转到第…

记录些RAG中Chunk切分方法

非结构化数据 在处理非结构化数据时&#xff0c;文本切分策略的选择至关重要&#xff0c;以保持信息完整性和提高检索效率。以下是一些有效的切分方法&#xff1a; 固定长度切分&#xff1a;将文本按照固定的字数或词数进行切分&#xff0c;例如每个文档切分成300个字或300个…