设计模式讲解02—责任链模式(Chain)

1. 概述

定义责任链模式是一种行为型模式,在这个模式中,通常创建了一个接收者对象的链来处理请求,该请求沿着链的顺序传递。直到有对象处理该请求为止,从而达到解耦请求发送者和请求处理者的目的。

解释责任链模式通过将多个处理器(处理对象)以链式结构连接起来,使得请求沿着这条链传递,直到有一个处理器处理该请求为止。责任链模式允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

⭐什么是行为型模式?

答:行为型模式主要用于描述对类或对象怎样交互和怎样分配职责。行为型模式 (Behavioral Pattern) 是对 在不同的对象之间划分责任和算法的抽象化

2. 优缺点

优点:

  1. 降低耦合度:请求发送者和接收者都没有对方的明确信息,而是通过抽象处理器来链接。实现了请求的发送者和处理者之间的解耦。
  2. 灵活性:可以动态地增加或删除处理器,方便扩展和维护。
  3. 易于实现:在责任链模式中,每个具体的处理器只需要实现自己的功能即可,不需要知道整个请求链的存在,这样更加容易实现其功能。

缺点:

  1. 不能保证请求一定会被处理:在责任链模式中,由于请求的处理是由多个对象负责的,所以不能保证请求一定会被处理,存在由于漏洞导致请求无响应的风险。
  2. 性能问题:在应用责任链模式时需要控制链中的处理器数量,过多的处理器会导致处理时间增加,从而影响系统性能。
  3. 调试困难:责任链模式中的处理器是动态组合的,处理逻辑较为复杂,因此需要进行详细的测试和调试。

3. 使用场景

3.1. 应用实例

  1. 请假申请流程:公司内部的请假申请一般需要经过多级审批,每个审批者的职责不同,可以通过责任链模式实现申请者与处理者之间的解耦,让申请者的请求依次经过各个处理者的处理,直到最终得到审批结果。
  2. 商品退换货:在线商场中,如果用户需要对商品进行退换货,涉及到订单创建、退货申请、快递配送等诸多步骤,这些步骤可以通过责任链模式实现,让每个处理者负责自己的任务,将责任链串接起来,以便完成整个退换货流程。
  3. 请求处理中心:当一个请求需要经过多个处理节点进行处理时,可以采用责任链模式来组织这些处理节点,使得请求在节点之间循环传递,直到得到最终结果。例如,大型网站的访问请求处理中心,就可以采用责任链模式来处理请求。
  4. 系统安全中心:当系统发生安全威胁时,可以采用责任链模式来组织安全相关的处理节点,对异常数据进行检测和拦截,保障系统安全稳定运行。

3.2. 程序场景

  1. 请求的处理顺序不确定:如果一个系统中存在多个处理请求的对象,且请求的处理可能需要先后顺序,则可以采用责任链模式,让不同的处理对象构成责任链,依次对请求进行处理。
  2. 有多个对象可需要处理请求:如果一个请求可能需要由多个对象来进行处理,而这些处理对象之间相互独立,不需要知道其他处理对象的存在,则可以采用责任链模式来实现请求的处理。
  3. 需要动态安排处理流程:如果处理流程需要动态安排,可以通过动态组合责任链节点来实现。即根据实际需求,动态安排责任链的执行顺序和强度。
  4. 需要在不影响代码整体结构的情况下,进行功能扩展:使用责任链模式可以方便地扩展系统的功能,对业务逻辑和系统结构的初始设计基本无影响,只需要添加新的处理节点、修改处理节点间的联系即可。

4. 结构⭐

责任链模式包含以下几个主要角色:

  • 抽象处理器(Handler)定义一个处理请求的接口,通常包含一个处理请求的方法(如 handleRequest)和一个指向下一个处理者的引用(后继者)。
  • 具体处理器(ConcreteHandler)实现了抽象处理器接口,负责处理请求。如果能够处理该请求,则直接处理;否则,将请求传递给下一个处理者。
  • 客户端(Client)创建处理者对象,并将它们连接成一条责任链。通常,客户端只需要将请求发送给责任链的第一个处理者,无需关心请求的具体处理过程。

5. 代码实现

5.1. 需求介绍

我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器判断消息的级别是否属于自己的级别,如果是则相应地打印出来,否则不打印并把消息传给下一个记录器。

5.2. 代码演示

  1. 创建一个抽象的记录器类(抽象处理器)
/*** @Description 记录器类 —— 抽象处理器* @Author gongming.Zhang* @Date 2024/11/6 10:39* @Version 1.0*/
public abstract class AbstractLogger {public static final Integer INFO = 1;public static final Integer DEBUG = 2;public static final Integer ERROR = 3;// protected:对本包以及不同包的子类可见protected Integer level;// 责任链中的下一个元素protected AbstractLogger nextLogger;public void setNextLogger(AbstractLogger nextLogger) {this.nextLogger = nextLogger;}public void logMessage(int level, String message) {if (this.level <= level) {write(message);}// 核心逻辑,链式连接多个处理器if (nextLogger != null) {nextLogger.logMessage(level, message);}}// 抽象方法,具体的处理器去实现对应的逻辑protected abstract void write(String message);
}

  1. 创建扩展了该记录器抽象类的具体实现类(具体抽象类)
/*** @Description 控制台日志类* @Author gongming.Zhang* @Date 2024/11/6 10:55* @Version 1.0*/
public class ConsoleLogger extends AbstractLogger {public ConsoleLogger(int level) {this.level = level;}@Overrideprotected void write(String message) {System.out.println("Standard Console::Logger: " + message);}
}
/*** @Description 报错日志类* @Author gongming.Zhang* @Date 2024/11/6 10:58* @Version 1.0*/
public class ErrorLogger extends AbstractLogger {public ErrorLogger(int level){this.level = level;}@Overrideprotected void write(String message) {System.out.println("Error Console::Logger: " + message);}
}
/*** @Description 文件日志类* @Author gongming.Zhang* @Date 2024/11/6 10:58* @Version 1.0*/
public class FileLogger extends AbstractLogger {public FileLogger(int level){this.level = level;}@Overrideprotected void write(String message) {    System.out.println("File::Logger: " + message);}
}

  1. 创建不同类型的记录器,并赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。(客户端)
/*** 客户端 Client** @return 返回链头*/
private static AbstractLogger getChainOfLoggers() {AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);// 设置链路errorLogger.setNextLogger(fileLogger);fileLogger.setNextLogger(consoleLogger);return errorLogger;
}/*** 测试*/
@Test
void testChainDesignPatterns() {AbstractLogger loggerChain = getChainOfLoggers();loggerChain.logMessage(AbstractLogger.INFO, "This is an information");loggerChain.logMessage(AbstractLogger.DEBUG, "This is a debug level information.");loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information.");
}

结果:

Standard Console::Logger: This is an information.
File::Logger: This is a debug level information.
Standard Console::Logger: This is a debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.

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

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

相关文章

Java | Leetcode Java题解之第542题01矩阵

题目&#xff1a; 题解&#xff1a; class Solution {static int[][] dirs {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};public int[][] updateMatrix(int[][] matrix) {int m matrix.length, n matrix[0].length;// 初始化动态规划的数组&#xff0c;所有的距离值都设置为一个很大…

ServletContext介绍

文章目录 1、ServletContext对象介绍1_方法介绍2_用例分析 2、ServletContainerInitializer1_整体结构2_工作原理3_使用案例 3、Spring案例源码分析1_注册DispatcherServlet2_注册配置类3_SpringServletContainerInitializer 4_总结 ServletContext 表示上下文对象&#xff0c;…

virtualBox部署minikube+istio

环境准备 virtualBox安装 直接官网下载后安装即可&#xff0c;网上也有详细教程。镜像使用的centos7。 链接&#xff08;不保证还可用&#xff09;&#xff1a;http://big.dxiazaicc.com/bigfile/100/virtualbox_v6.1.26_downcc.com.zip?auth_key1730185635-pWBtV8LynsxPD0-0-…

QT 实现绘制汽车仪表盘

1.界面实现效果 以下是具体的项目需要用到的效果展示,通常需要使用QPainter类来绘制各种图形和文本,包括一个圆形的仪表盘、刻度、指针和数字。 2.简介 分为以下几个部分,首先设置抗锯齿 painter.setRenderHint(QPainter::Antialiasing)。 QPainter p(this);p.setRender…

Node.js——fs模块-文件读取

1、文件读取&#xff1a;通过程序从文件中去除其中的数据 2、方法 方法 说明 readFile 异步读取 readFileSync 同步读取 createReadStrean 流式读取 3、readFile 异步读取 语法&#xff1a; 本文的分享到此结束&#xff0c;欢迎大家评论区一同讨论学习&#xff0c;下一…

cv2.threshold利用OSTU方法分割图像的前景和背景

OSTU方法&#xff0c;又称大津法或最大类间方差法&#xff0c;是一种在图像处理中广泛应用的自动阈值选择方法。该方法由日本学者大津&#xff08;Nobuyuki Otsu&#xff09;于1979年提出&#xff0c;旨在通过最大化前景与背景之间的类间方差来自动确定一个最佳阈值&#xff0c…

Perforce《2024游戏技术现状报告》Part2:游戏引擎、版本控制、IDE及项目管理等多种开发工具的应用分析

游戏开发者一直处于创新前沿。他们的实践、工具和技术受到各行各业的广泛关注&#xff0c;正在改变着组织进行数字创作的方式。 近期&#xff0c;Perforce发布了《2024游戏技术现状报告》&#xff0c;通过收集来自游戏、媒体与娱乐、汽车和制造业等高增长行业的从业者、管理人…

编写虚拟的GPIO控制器的驱动程序:和pinctrl的交互使用

往期内容 本专栏往期内容&#xff1a; Pinctrl子系统和其主要结构体引入Pinctrl子系统pinctrl_desc结构体进一步介绍Pinctrl子系统中client端设备树相关数据结构介绍和解析inctrl子系统中Pincontroller构造过程驱动分析&#xff1a;imx_pinctrl_soc_info结构体Pinctrl子系统中c…

数据结构代码题--排序算法(快排),二叉树的基本知识,链表的基本操作引申

排序算法&#xff1a; 完成比完美更重要&#xff01; 题目中常考的是平均时间复杂度&#xff1a;但是具体计算时&#xff0c;能用最坏就用最坏 插入&#xff1a;直接插&#xff0c;希尔 交换&#xff1a;冒泡&#xff0c;快排 选择&#xff1a;简单选择&#xff0c;堆排 归…

外包干了4年,技术退步太明显了。。。。。

先说一下自己的情况&#xff0c;本科生生&#xff0c;20年通过校招进入武汉某软件公司&#xff0c;干了差不多4年的功能测试&#xff0c;今年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能…

VS2013安装报错“windows程序兼容性模式已打开,请将其关闭 ”解决方案

windows程序兼容性模式已打开,请将其关闭 在安装VS2013语言包的时候报错&#xff1a;windows程序兼容性模式已打开,请将其关闭 还会经常遇到这个错误&#xff1a;有一个安装程序已经运行 第一个问题解决办法&#xff1a; 按winr&#xff0c;输入cmd 输入 安装包路径 /Uninstal…

fastapi_socketio连接vue的socktio.client

环境 windows 11 python 3.11 fastapi 0.108.0 fastapi-socketio 0.0.10 vue2 “socket.io-client”: “^4.6.1”, 提示&#xff1a;如果遇到跨域问题自行解决 fastapi 使用fastapi-scoketio下的SocketManager, 可以看到接口解释如下&#xff1a; 所以默认配置是客户端连接时…

使用 GitHub Actions 部署到开发服务器的详细指南

使用 GitHub Actions 部署到开发服务器的详细指南 在本篇博客中&#xff0c;我们将介绍如何使用 GitHub Actions 实现自动化部署&#xff0c;将代码从 GitHub 仓库的 dev 分支自动部署到开发服务器。通过这种方式&#xff0c;可以确保每次在 dev 分支推送代码时&#xff0c;服…

常见 HTTP 状态码分类和解释及服务端向前端返回响应时的最完整格式

目前的开发项目&#xff0c;准备明年的国产化&#xff0c;用了十年的自研系统借这个机会全部重写&#xff0c;订立更严格的规范&#xff0c;这里把返回格式及对应状态码记录一下。 常见 HTTP 状态码及解释 HTTP 状态码用于表示客户端请求的响应状态&#xff0c;它们分为五类&a…

使用PyCharm连接虚拟机运行spark任务,本地开发:远程提交测试

在本地写代码&#xff0c;右键运行&#xff0c;将代码自动提交到集群上 spark是Standalone集群 1) 集群环境准备好 #启动集群&#xff1a;第一台机器 start-dfs.sh cd /opt/installs/spark sbin/start-master.sh sbin/start-workers.sh sbin/start-history-server.sh 2) Wi…

XHCI 1.2b 规范摘要(12)

系列文章目录 XHCI 1.2b 规范摘要&#xff08;一&#xff09; XHCI 1.2b 规范摘要&#xff08;二&#xff09; XHCI 1.2b 规范摘要&#xff08;三&#xff09; XHCI 1.2b 规范摘要&#xff08;四&#xff09; XHCI 1.2b 规范摘要&#xff08;五&#xff09; XHCI 1.2b 规范摘要…

多分类logistic回归分析案例教程

因变量为无序多分类变量&#xff0c;比如研究成人早餐选择的相关因素&#xff0c;早餐种类包括谷物类、燕麦类、复合类&#xff0c;此时因变量有三种结局&#xff0c;而且三种早餐是平等的没有顺序或等级属性&#xff0c;此类回归问题&#xff0c;可以使用多分类Logistic回归进…

读取数量不定的输入数据

#include <iostream> using namespace std; int main() {int sum 0, value 0;//读取数据直到遇到文件尾while (cin >> value) {sum value;}cout << sum;return 0; }

Kubernetes的基本构建块和最小可调度单元pod-0

文章目录 一&#xff0c;什么是pod1.1pod在k8s中使用方法&#xff08;1&#xff09;使用方法一&#xff08;2&#xff09;使用方法二 1.2pod中容器的进程1.3pod的网络隔离管理&#xff08;1&#xff09;pause容器的作用 1.4 Pod分类&#xff1a;&#xff08;1&#xff09;自主式…

unity3d————四元数概念

一、定义与表示 四元数是由一个实数部分和三个虚数部分组成&#xff0c;通常表示为q w xi yj zk&#xff0c;其中w是实数&#xff0c;x、y、z是实数系数&#xff0c;i、j、k是虚数单位&#xff0c;满足以下关系&#xff1a; i j k -1ij k&#xff0c;ji -kjk i&…