技术成神之路:设计模式(八)责任链模式

介绍

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许多个对象依次处理请求,避免请求的发送者和接收者之间的显式耦合。该模式通过将多个可能处理请求的对象连接成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

1.定义


责任链模式为请求创建一个接收者对象的链。这种模式给予多个对象处理请求的机会,从而解耦发送者和接收者。

2.主要作用


  1. 解耦发送者和接收者:发送者无需知道链中的具体接收者,只需将请求发送给链的头部。每个接收者只需要实现处理请求的方法即可。

  2. 动态的处理链:责任链可以动态配置和调整,可以根据需要增加或修改链中的处理者,灵活性较高。

  3. 增强可扩展性:可以根据业务需求方便地增加或者修改处理节点,符合开闭原则。

3.解决的问题


空口无凭,咱举例说明😉😉

3.1 解耦发送者和接收者

示例:
在一个电商系统中,订单的支付方式验证可以通过责任链模式来处理。例如,支付方式验证可以依次由信用卡支付、支付宝、微信支付等组成一个处理链,系统根据订单中选择的支付方式逐个验证,直到找到能够处理该支付方式的处理者。

3.2 动态确定处理链

示例:
在一个工作流系统中,根据不同的流程状态和权限要求,可以动态地配置审批流程。例如,一个采购审批流程可能需要在不同金额范围内由不同级别的管理者审批,责任链模式可以根据采购金额动态确定审批人。

3.3 增强系统的可扩展性

示例:
在一个日志记录系统中,可以使用责任链模式来处理日志的级别。例如,如果日志级别是DEBUG,则可以由DebugLogger处理;如果是INFO,则由InfoLogger处理;如果是ERROR,则由ErrorLogger处理。如果未来增加了新的日志级别,只需添加新的处理者即可,不影响原有代码。

4.模式原理


包含角色:

  1. 抽象处理者(Handler):定义处理请求的接口,并维护一个指向下一个处理者的引用。
  2. 具体处理者(ConcreteHandler):实现抽象处理者的接口,处理请求的具体逻辑。如果可以处理请求,则处理;否则将请求传递给下一个处理者。
  3. 客户端(Client):创建责任链,并将请求发送给链的第一个处理者。

UML类图:
在这里插入图片描述
示例代码:

定义处理器接口

abstract class Logger {public static int INFO = 1;public static int DEBUG = 2;public static int ERROR = 3;protected int level;//next element in chain or responsibilityprotected Logger nextLogger;public void setNextLogger(Logger nextLogger){this.nextLogger = nextLogger;}public void logMessage(int level, String message){if(this.level <= level){write(message);}if(nextLogger != null){nextLogger.logMessage(level, message);}}abstract protected void write(String message);
}

创建具体的处理器

class ConsoleLogger extends Logger {public ConsoleLogger(int level){this.level = level;}@Overrideprotected void write(String message) {        System.out.println("Standard Console::Logger: " + message);}
}class ErrorLogger extends Logger {public ErrorLogger(int level){this.level = level;}@Overrideprotected void write(String message) {        System.out.println("Error Console::Logger: " + message);}
}class FileLogger extends Logger {public FileLogger(int level){this.level = level;}@Overrideprotected void write(String message) {System.out.println("File::Logger: " + message);}
}

设置链条

public class ChainPatternDemo {private static Logger getChainOfLoggers(){Logger errorLogger = new ErrorLogger(Logger.ERROR);Logger fileLogger = new FileLogger(Logger.DEBUG);Logger consoleLogger = new ConsoleLogger(Logger.INFO);errorLogger.setNextLogger(fileLogger);fileLogger.setNextLogger(consoleLogger);return errorLogger;  }public static void main(String[] args) {Logger loggerChain = getChainOfLoggers();loggerChain.logMessage(Logger.INFO, "这是一个信息.");loggerChain.logMessage(Logger.DEBUG, "这是一个debug信息.");loggerChain.logMessage(Logger.ERROR, "这是一个error信息.");}
}

上面代码创建了一个日志处理链:错误日志处理器 -> 文件日志处理器 -> 控制台日志处理器。根据日志消息的级别,消息会被相应级别的处理器处理,如果这个处理器级别不足以处理该消息,则消息会传递给链中的下一个处理器。

5.优缺点


优点:

  • 降低耦合度
  • 增加新的命令处理类很方便

缺点:

  • 不能保证请求一定被接收: 就像switch要加default一样,在链的末端未被处理。
  • 性能问题:如果链条过长可能会出现性能问题,几乎可以忽略。

6.应用场景


  1. 多级请求:当一个请求可以由多个对象来处理,但具体由哪个对象处理则在运行时动态决定。
  2. 审批流程:如公司的采购审批、请假审批等,每个审批阶段都可以视为链上的一个处理节点。
  3. 事件处理系统:如GUI中的事件处理或者框架中的事件传递,比如Java的AWT或Swing。
  4. 日志记录:根据消息的严重性级别决定日志记录的方式,各种处理方式如写入文件、通过电子邮件发送或其他。
  5. 拦截过滤器:网络请求的拦截过滤也可以使用责任链模式设计,例如Servlet的Filter链。

7.总结


责任链模式与我们的生活息息相关,比如:项目出了严重BUG 需要找到责任人,测试,开发,项目经理总要有一个来背锅的,还有 村长、乡长、县长、市长… 一级一级的就构成了一条链,可能举例不是很恰当,但大概就是这个意思,这种设计模式提高了系统的灵活性和可扩展性,符合开闭原则和单一职责原则,但也需要注意处理者的配置和性能问题。

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

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

相关文章

Cadence23导入板框时的疑难杂症

1.为啥导入板框之后元器件找不到了呢&#xff1f; 因为导入板框的时候没有勾选 增加量 &#xff0c;导致导入的板框新建了一个文件&#xff1a; 2.导入板框之后3D显示还是不没有导入呀&#xff1f; 那是因为导入的板框还带有铜皮属性&#xff0c;需要change命令把其换为板框…

【算法】算法模板

算法模板 文章目录 算法模板简介数组字符串列表数学树图动态规划 简介 博主在LeetCode网站中学习算法的过程中使用到并总结的算法模板&#xff0c;在算法方面算是刚过初学者阶段&#xff0c;竞赛分数仅2000。 为了节省读者的宝贵时间&#xff0c;部分基础的算法与模板未列出。…

51单片机13(动态数码管实验)

一、数码管动态显示原理 1、动态显示是利用减少段选线&#xff0c;分开位选线&#xff0c;利用位选线不同时选择通断&#xff0c;改变段选数据来实现的。 &#xff08;1&#xff09;多位数码管依然可以进行静态的一个显示&#xff0c;那么在前面我们介绍静态数码管的时候&…

Nginx(详解以及如何使用)

目录 1. 什么是Nginx&#xff1f; 2. 为什么使用nginx? 3. 安装nginx 3.1 安装nginx的依赖插件 3.2 下载nginx 3.3 创建一个目录作为nginx的安装路径 3.4 解压 3.5 进入解压后的目录 3.6 指定nginx的安装路径 3.7 编译和安装nginx 3.8 启动nginx 3.9 访问nginx 4. ngin…

【python】Python中闭包的是什么,闭包原理分析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

MongoDB教程(十四):MongoDB查询分析

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、查询分…

队列及其应用(用栈实现队列 力扣225)

队列概念 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out) 入队列&#xff1a;进行插入操作的一端称为队尾 出队列&#xff1a;进行删除操作的一端称为队头 队列的代码…

09.甜甜圈旋转加载动画 计数器

甜甜圈旋转加载动画 创建一个甜甜圈形状的旋转加载动画,可用于指示内容的加载。 为整个元素使用半透明的 border。排除一侧,它将作为甜甜圈的加载指示器。定义并使用合适的动画,使用 transform: rotate() 旋转元素。<body><div class="donut"></div&…

基于JAVA+SpringBoot+Vue+uniapp的微信小程序点餐平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 点餐小程序主要为小个…

java——类变量和类方法;代码块;内部类

一、类变量和类方法 1.1、类变量 1.1.1、类变量内存布局(静态变量放在哪里&#xff1f;) 1、JVM7及以前的近代变量放在方法区中&#xff1b;JVM8以后的静态变量放在堆中 2、不管static变量在哪里&#xff0c;共识&#xff1a; 1&#xff09;Static变量是同一个类所有对象共…

昇思25天学习打卡营第17天 | 基于MindSpore实现BERT对话情绪识别

昇思25天学习打卡营第17天 | 基于MindSpore实现BERT对话情绪识别 文章目录 昇思25天学习打卡营第17天 | 基于MindSpore实现BERT对话情绪识别BERT模型对话情绪识别BERT模型的文本情绪分类任务数据集数据下载数据加载与预处理 模型构建模型验证模型推理 总结打卡 BERT模型 BERT&…

【Espressif-ESP32S3】【VScode】安装【ESP-IDF】插件及相关工具链

一、ESP-IDF简介 二、VScode安装ESP-IDF插件 三、安装ESP-IDF、ESP-IDF-Tools以及相关工具链 四、测试例程&编译烧录 五、IDF常用指令 资料下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/15Q2rl2jpIaKfj5rATkYE6g?pwdGLNG 提取码&#xff1a;GLNG 一、ESP-…

IntelliJ IDEA 2024.1 最新变化 附问卷调查 AI

IntelliJ IDEA 2024.1 最新变化 问卷调查项目在线AI IntelliJ IDEA 2024.1 最新变化关键亮点全行代码补全 Ultimate对 Java 22 功能的支持新终端 Beta编辑器中的粘性行 AI AssistantAI Assistant 改进 UltimateAI Assistant 中针对 Java 和 Kotlin 的改进代码高亮显示 Ultimate…

Android14之调试广播实例(二百二十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

shell脚本检查OGG同步进程状态

服务器环境中在root用户下部署了ogg同步进程&#xff0c;在oracle用户下也部署了同步进程。在不用脚本检查的情况下&#xff0c;进程需要在root用户和oracle用户下来回切换&#xff0c;比较麻烦&#xff0c;所以考虑用脚本实现&#xff0c;在root用户下一键检查root用户和oracl…

Grid Search:解锁模型优化新境界

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

【数据结构初阶】复杂度

目录 一、时间复杂度 1、时间复杂度的概念 2、大O的渐进表示法 3、常见的时间复杂度计算举例 二、空间复杂度 1、空间复杂度的概念 2、常见的空间复杂度计算举例 三、常见复杂度对比 正文开始—— 前言 一个算法&#xff0c;并非越简洁越好&#xff0c;那该如何衡量一个算法…

源码安装 AMD GPGPU 生态 ROCm 备忘

0, 前言 如果初步接触 AMD这套&#xff0c;可以先在ubuntu上使用apt工具安装&#xff0c;并针对特定感兴趣的模块从源码编译安装替换&#xff0c;并开展研究。对整体感兴趣时可以考虑从源码编译安装整个ROCm生态。 1, 预制二进制通过apt 安装 待补。。。 2, 从源码安装 sudo …

C:一些题目

1.分数求和 计算1/1-1/21/3-1/41/5 …… 1/99 - 1/100 的值 #include <stdio.h>int main(){double sum 0.0; // 使用 double 类型来存储结果&#xff0c;以处理可能的小数部分int sign 1; // 符号标志&#xff0c;初始为 1 表示正数for (int i 1; i < 100; i)…

Vue3 内置组件Teleport以及Susponse

1、Teleport 1.1 概念 将组件模版中的指定的dom挂载&#xff08;传送&#xff09;到指定的dom元素上&#xff0c;如挂载到body中&#xff0c;挂载到#app选择器上面。 1.2 应用场景 经典案例如&#xff1a;模态框。 <template><teleport to"body">&l…