当前位置: 首页 > news >正文

设计模式探索:责任链模式

1. 什么是责任链模式

责任链模式 (Chain of Responsibility Pattern) 是一种行为型设计模式。定义如下:

  • 避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。
  • 将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。
    在这里插入图片描述

2. 责任链模式的作用

  • 将请求和请求的处理进行解耦,提高代码的可扩展性。

3. 责任链模式的结构

在这里插入图片描述

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

  • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接(链上的每个处理者都有一个成员变量来保存对于下一处理者的引用)。
  • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

在实际开发中,责任链模式可能会增加一个责任链管理者来管理具体的处理者。

4. 责任链模式在实际开发中的应用

在 SpringBoot 中,责任链模式的实践方式有多种,以下是一种示例:一个下单流程的多个独立检查逻辑。
在这里插入图片描述

4.1 实现方式1
  1. 创建 Pojo, 下单对象
public class OrderContext {private String seqId;private String userId;private Long skuId;private Integer amount;private String userAddressId;// Getters and setters
}
  1. 创建处理者接口
public interface OrderHandleIntercept {int sort();OrderContext handle(OrderContext context);
}
  1. 创建具体处理者类
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {@Overridepublic int sort() {return 1; // 执行顺序为 1}@Overridepublic OrderContext handle(OrderContext context) {System.out.println("通过seqId,检查客户是否重复下单");return context;}
}@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {@Overridepublic int sort() {return 2; // 执行顺序为 2}@Overridepublic OrderContext handle(OrderContext context) {System.out.println("检查请求参数是否合法,并且获取客户的银行账户");return context;}
}@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {@Overridepublic int sort() {return 3; // 执行顺序为 3}@Overridepublic OrderContext handle(OrderContext context) {System.out.println("检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额");return context;}
}
  1. 处理器链类
@Component
public class OrderHandleChainService implements ApplicationContextAware {private List<OrderHandleIntercept> handleList = new ArrayList<>();@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {Map<String, OrderHandleIntercept> serviceMap = applicationContext.getBeansOfType(OrderHandleIntercept.class);handleList = serviceMap.values().stream().sorted(Comparator.comparing(OrderHandleIntercept::sort)).collect(Collectors.toList());}public OrderContext execute(OrderContext context) {for (OrderHandleIntercept handleIntercept : handleList) {context = handleIntercept.handle(context);}return context;}
}
  1. 进行单元测试
@Autowired
private OrderHandleChainService orderHandleChainService;@Test
public void test02() {orderHandleChainService.execute(new OrderContext());
}
  1. 执行结果
通过seqId,检查客户是否重复下单
检查请求参数是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额
4.2 实现方式2

通过注解 @Order 来指定排序

@Order(1)
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {//...省略
}@Order(2)
@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {//...省略
}@Order(3)
@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {//...省略
}

修改 OrderHandleChainService

@Component
public class OrderHandleChainService {@Autowiredprivate List<OrderHandleIntercept> handleList;public OrderContext execute(OrderContext context) {for (OrderHandleIntercept handleIntercept : handleList) {context = handleIntercept.handle(context);}return context;}
}
4.3 实现方式3

通过定义抽象类来实现责任链设计模式

public abstract class AbstractOrderHandle {private AbstractOrderHandle next;public AbstractOrderHandle getNext() {return next;}public void setNext(AbstractOrderHandle next) {this.next = next;}public abstract OrderContext handle(OrderContext orderContext);public OrderContext execute(OrderContext context) {context = handle(context);if (getNext() != null) {getNext().execute(context);}return context;}
}

分别创建处理类

@Component
@Order(1)
public class RepeatOrderHandle extends AbstractOrderHandle {@Overridepublic OrderContext handle(OrderContext context) {System.out.println("通过seqId,检查客户是否重复下单");return context;}
}@Component
@Order(2)
public class ValidOrderHandle extends AbstractOrderHandle {@Overridepublic OrderContext handle(OrderContext context) {System.out.println("检查请求参数,是否合法,并且获取客户的银行账户");return context;}
}@Component
@Order(3)
public class BankOrderHandle extends AbstractOrderHandle {@Overridepublic OrderContext handle(OrderContext context) {System.out.println("检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额");return context;}
}

创建一个责任链管理器

@Component
public class OrderHandleManager {@Autowiredprivate List<AbstractOrderHandle> orderHandleList;@PostConstructpublic void initChain() {int size = orderHandleList.size();for (int i = 0; i < size; i++) {if (i == size - 1) {orderHandleList.get(i).setNext(null);} else {orderHandleList.get(i).setNext(orderHandleList.get(i + 1));}}}public OrderContext execute(OrderContext context) {OrderContext execute = orderHandleList.get(0).execute(context);return context;}
}

测试

@Autowired
private OrderHandleManager orderHandleManager;@Test
public void test02() {orderHandleManager.execute(new OrderContext());
}

运行结果与预期一致:

通过seqId,检查客户是否重复下单
检查请求参数,是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额

5. 职责链模式总结

职责链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许多个对象处理同一个请求,从而避免请求的发送者和接收者之间的耦合关系。这种模式为请求的处理提供了一条清晰的链,每个对象可以决定是否处理该请求或者将请求转发给链中的下一个对象。

职责链模式的优点:

  1. 降低耦合度:发送者和接收者之间没有直接的联系,降低了系统组件之间的耦合度。
  2. 增强灵活性:可以在运行时动态地添加或移除职责链中的处理对象,提高了系统的灵活性和可扩展性。
  3. 明确责任分配:每个处理对象只关注自己的职责范围,责任分配更加明确。

职责链模式的缺点:

  1. 请求处理不确定性:不能保证请求一定会被处理,如果链中的所有对象都不处理请求,请求将被忽略。
  2. 系统性能影响:请求可能需要通过较长的链进行传递,可能会对性能产生影响。
  3. 客户端复杂性增加:客户端可能需要了解整个职责链的配置,增加了客户端的使用复杂性。

职责链模式的使用场景:

  1. 多个对象处理请求:当一个请求需要多个对象依次处理时,可以使用职责链模式。
  2. 处理逻辑不明确:在运行时根据请求的类型动态选择处理对象,不希望客户端知道具体的处理逻辑。

职责链模式的实现可以通过组合多个具体处理者对象,并设置它们的后继者,形成一个处理链。当请求发出时,链中的每个对象依次判断是否能够处理该请求,如果可以处理则执行处理操作,否则将请求转发给链中的下一个对象。

这种模式在实际应用中非常广泛,例如在GUI应用程序的事件处理、工作流审批流程、过滤器链等场景中都有应用。通过使用职责链模式,可以提高系统的模块化和灵活性,同时降低组件之间的依赖关系。

相关文章:

设计模式探索:责任链模式

1. 什么是责任链模式 责任链模式 (Chain of Responsibility Pattern) 是一种行为型设计模式。定义如下&#xff1a; 避免将一个请求的发送者与接收者耦合在一起&#xff0c;让多个对象都有机会处理请求。将接收请求的对象连接成一条链&#xff0c;并且沿着这条链传递请求&…...

OceanBase 配置项系统变量实现及应用详解(3):新增配置项的方法

本专题的第一篇文章&#xff0c;配置项的定义及使用方法&#xff0c;详细阐述了配置项的基础用法。对于那些对源码抱有浓厚兴趣的同学来说&#xff0c;或许还希望深入了解配置项的实现原理&#xff0c;甚至渴望亲自添加新的配置项&#xff0c;以满足个性化的功能需求。 本文通…...

PCI PTS 硬件安全模块(HSM)模块化安全要求 v5.0

符合条件的 PCI SSC 利益相关者在 30 天的意见征询 (RFC) 期间审查 PCI PTS 硬件安全模块 (HSM) 模块化安全要求 v5.0 草案并提供反馈。 PCI PTS 硬件安全模块(HSM)模块化安全要求 v5.0图 从 7 月 8 日到 8 月 8 日&#xff0c;邀请符合条件的 PCI SSC 利益相关者在 30 天的意见…...

javaweb中的请求与响应--基于postman工具的应用(附带postman的详细安装步骤)

一、前言 后端的第一天感觉难度就上来了&#xff0c;可能是基础太过薄弱了吧。目前看视频已经有点跟不上了&#xff0c;果然15天想要拿下还是太勉强了点。30天还差不多。不知道读者们有没有好好的去学这方面的知识&#xff0c;没有什么是学不会的&#xff0c;关键是坚持。 Po…...

StarRocks下载使用说明和基础操作

简介 StarRocks 是一款高性能分析型数据仓库&#xff0c;使用向量化、MPP 架构、CBO、智能物化视图、可实时更新的列式存储引擎等技术实现多维、实时、高并发的数据分析。StarRocks 既支持从各类实时和离线的数据源高效导入数据&#xff0c;也支持直接分析数据湖上各种格式的数…...

桥接模式案例

桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;它将抽象部分与实现部分分离&#xff0c;使它们可以独立变化。桥接模式通过创 建一个桥接接口&#xff0c;将抽象部分和实现部分连接起来&#xff0c;从而实现两者的解耦。下面是一个详细的桥接…...

Spring源码二十二:Bean实例化流程五

上一篇Spring源码二十一&#xff1a;Bean实例化流程四&#xff0c;咱们主要分析里createBeanInstance方法Spring给我们提供给的FactoryMethod方法&#xff0c;举例说明了factoryMethod属性如何使用&#xff0c;同时简单讨论了具体实现逻辑。 这一篇咱们将进入反射实例化Bean&am…...

Unity3D中UI层级改变详解

在Unity3D开发中&#xff0c;UI层级的调整是常见的需求&#xff0c;它直接关系到用户界面(UI)元素的显示顺序。在Unity的UI系统中&#xff0c;主要使用UGUI&#xff08;Unitys Graphical User Interface&#xff09;来实现界面布局和元素展示。本文将详细讲解Unity3D中如何改变…...

centos安装数据库同步工具sqoop并导入数据,导出数据,添加定时任务

目录 1.安装jdk 1.1上传jdk安装包到/opt目录下并解压 1.2解压 1.3配置环境变量 2.安装hadoop 2.1.下载hadoop 2.2.解压hadoop 2.3配置环境变量 3.安装sqoop 3.1下载 3.2解压 3.3下载依赖包并复制到指定位置 3.3.1下载commons-lang-2.6-bin.tar.gz 3.3.2将mysql-c…...

asp .net core 避免请求body数据量过大

方法1&#xff0c; 全局避免 引入包 dotnet add package Microsoft.AspNetCore.Http.Features using Microsoft.AspNetCore.Http.Features;public void ConfigureServices(IServiceCollection services) {services.Configure<FormOptions>(options >{// 设置允许的最…...

搭建discuz论坛(lvs+nginx+http+mysql+nfs)8台服务器

搭建discuz论坛&#xff08;lvsnginxhttpmysqlnfs&#xff09; 一、IP规划 服务名IP地址服务LVS1192.168.100.110keepalivedipvsadmLVS2192.168.100.111keepalivedipvsadmnginx1192.168.100.113nginxnginx2192.168.100.114nginxnfs192.168.100.116nfs-utilweb1192.168.100.11…...

就业平台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;企业管理&#xff0c;企业类型管理&#xff0c;留言板管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;招聘信息&#xff0c;简历&#xff0c;我的 …...

hid-ft260驱动学习笔记 5 - ft260_i2c_probe

目录 1. 保存ft260_device到私有数据 2. 初始化I2C设备分配属性 3. 添加I2C适配器 4. 初始化GPIO 5. ft260_i2c_algo 5.1 ft260_functionality 5.2 ft260_i2c_xfer 5.3 ft260_smbus_xfer 6. ft260_i2c_quirks 这个函数是i2c的接口probe函数。 1. 保存ft260_device到私…...

Android上如何使用perfetto分析systrace

Android上如何使用perfetto分析systrace Perfetto 是一个用于性能分析的工具&#xff0c;提供了对 Android 系统内部工作情况的详细视图。它可以用来替代传统的 systrace 工具&#xff0c;提供更加全面的性能分析功能。以下是如何使用 Perfetto 分析 Systrace 数据的详细指南&…...

React Hooks学习笔记

一、usestate的使用方法-初始化state函数 import React, { useState } from "react"; function App() {const [count, setCount] useState(0);return (<div><p>点击{count}次</p><button onClick{() > setCount(count 1)}>点击</bu…...

BGP第二日

上图为今日所用拓扑 &#xff0c;其中R1和R4&#xff0c;R3和R5为EBGP邻居&#xff0c;R1和R3为IBGP邻居&#xff0c;AS200区域做OSPF动态路由 一.BGP建立邻居的六种状态 1.idle 空闲状态&#xff1a;建立邻居最初的状态 2.Connect 连接状态&#xff1a;在…...

rabbitmq集群创建admin用户之后,提示can access virtual hosts是No access状态

问题描述&#xff1a; 因业务需要使用的rabbitmq是3.7.8版本的&#xff0c;rabbitmq在3.3.0之后就允许使用guest账号的权限了&#xff0c;所以需要创建一个administrator标签的用户。 如下操作创建的用户&#xff1a; 创建完成之后就提示如下的报错&#xff1a; 注&#xff1a…...

ARM功耗管理之多核处理器启动

安全之安全(security)博客目录导读 思考&#xff1a;SecureBoot&#xff1f;多核处理器启动流程&#xff1f;PSCI启动方式&#xff1f; 一般嵌入式系统使用的都是对称多处理器&#xff08;Symmetric Multi-Processor, SMP&#xff09;系统&#xff0c;包含了多个cpu, 这几个cp…...

java使用easypoi模版导出word详细步骤

文章目录 第一步、引入pom依赖第二步、新建导出工具类WordUtil第三步、创建模版word4.编写接口代码5.导出结果示例 第一步、引入pom依赖 <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><…...

Android 内部保持数据的方式

Android内部保持数据的方式主要有五种&#xff0c;每种方式都有其特定的用途和优点。以下是详细的介绍&#xff1a; SQLite数据库 定义&#xff1a;SQLite是一个轻量级的、跨平台的数据库&#xff0c;所有的信息都存储在单一文件内&#xff0c;占用内存小&#xff0c;并且支持…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...