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

设计模式——Chain(责任链)设计模式

摘要

责任链设计模式是一种行为设计模式,通过链式调用将请求逐一传递给一系列处理器,直到某个处理器处理了请求或所有处理器都未能处理。它解耦了请求的发送者和接收者,允许动态地将请求处理职责分配给多个对象,支持请求的灵活传递或中断。

1. 责任链设计模式是什么

1.1. 责任链设计模式

责任链模式理解就是遍历某一个接口下所有的实现类中方法。责任链模式的核心思想就是通过链式调用将请求逐一传递给一系列处理器(实现了同一个接口的对象),直到某个处理器处理了请求,或者链中的所有处理器都未能处理该请求。

1.2. 责任链模式的基本工作原理:

  1. 处理者链:将多个处理者(通常是实现了相同接口的类)链接在一起,每个处理者负责处理请求的一个特定方面。
  2. 请求传递:请求会沿着责任链传递,每个处理者都会判断是否能够处理该请求,处理后返回或继续传递给下一个处理者。
  3. 终止条件:如果某个处理者能够处理该请求,链条上后续的处理者通常会被跳过,直接返回处理结果;如果没有处理者能处理,最终请求可能会失败。

1.3. 简化的责任链模式结构

可以把责任链模式理解为:

  • 链表结构:每个节点(处理器)持有对下一个节点的引用,依次处理请求。
  • 处理器接口:每个节点实现一个接口,负责具体的处理逻辑。

责任链模式(Chain of Responsibility Pattern)与 装饰器模式(Decorator Pattern)迭代器模式(Iterator Pattern) 在某些方面有相似之处,但它们的核心思想和使用场景略有不同。

特性

责任链模式

装饰器模式

目的

解耦请求的发送者和接收者,将请求交给多个处理者逐一处理

动态为对象添加功能,增强其行为

结构

请求按链式结构传递,每个处理者持有下一个处理者的引用

对原对象进行包装,增加额外功能

请求传递

请求沿着责任链传递,直到某个处理器处理请求或链终止

不传递请求,直接在原对象上增强功能

设计模式重点

请求处理的顺序和中断条件控制

通过包装原对象来动态增加功能

典型应用场景

多个处理器顺序处理请求,逐个判断并决定是否处理

动态为对象添加行为,功能扩展而不修改原对象代码

耦合性

请求发送者与接收者解耦,减少了依赖关系

可以灵活地为对象添加功能,扩展类的功能而不修改其代码

责任

每个处理者负责部分请求处理逻辑

每个装饰器负责对原对象的功能扩展

1.4. 责任链设计模式的作用

  1. 请求传递:每个处理者(链上的对象)都有一个引用指向下一个处理者。请求沿着链依次传递,直到被某个处理者处理或链结束。
  2. 解耦:发送方无需直接与处理方耦合,降低代码的复杂度。
  3. 可扩展性:可以灵活地添加、删除或修改链上的处理者,而不影响整体结构。
  4. 职责分离:每个处理者只关注自己能处理的部分,其余的请求传递给下一个处理者。

1.5. 责任链模式的优点

  1. 解耦请求与处理者:请求方不需要知道具体处理者是谁,降低耦合。
  2. 动态组合职责链:可以灵活地增加、删除或重排链中的处理节点。
  3. 代码清晰:将复杂的逻辑分解到多个处理节点中,职责单一。

1.6. 责任链模式的缺点

  1. 性能开销:当责任链过长时,可能带来性能问题。
  2. 调试困难:请求处理链条较长时,调试排查问题可能变得复杂。
  3. 不保证请求被处理:如果没有合适的处理者,可能导致请求最终未被处理。(执行链是有默认的顺序,可以借助Spring中@Order注解来实现有序)

2. 责任链模式类图实现

2.1. 责任链模式的结构

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

  1. Handler(处理者抽象类/接口):
    • 定义处理请求的接口,并存储下一个处理者的引用。
  1. ConcreteHandler(具体处理者):
    • 继承或实现 Handler,处理它负责的请求。如果无法处理,则将请求转发给下一个处理者。
  1. Client(客户端):
    • 创建责任链,并向链头发出请求。

3. 责任链模式使用场景

3.1. 多级请求处理

  • 当一个请求需要经过多个对象处理,且不明确具体是由哪个对象处理时。
  • 示例:
    • 日志系统:根据日志级别(DEBUG、INFO、WARN、ERROR)动态决定由哪个日志处理器处理。
    • 审批流:如贷款审批流程,依次经过组长、经理、总监的审批。

3.2. 请求处理职责动态变化

  • 处理职责可能会随时增减,且希望能灵活调整处理顺序。
  • 示例:风控规则引擎:新增或调整规则处理节点时,动态维护责任链。

3.3. 避免请求发送者与接收者耦合

  • 当请求发送者不需要知道接收者的具体实现时,可以通过责任链解耦。
  • 示例:支付系统:如多种支付渠道(银行卡、第三方支付、余额支付)按优先级尝试支付。

3.4. 请求的处理逻辑可以被分解

  • 请求的处理逻辑非常复杂,且可以拆分成多个步骤时,每个步骤都可以成为责任链上的一个节点。
  • 示例:HTTP 请求拦截器:如在请求到达服务器前,依次经过身份认证、权限验证、数据校验等。

3.5. 需要支持请求的灵活传递或中断

  • 某个处理器完成后,可以继续传递给下一个处理器,也可以选择中止传递。
  • 示例:事件处理机制:如 Java 的事件监听器,事件沿着监听器链依次传递,直到某个监听器处理完成。

3.6. 责任链具体场景示例

3.6.1. 风控规则链

在信贷风控中,每个用户的申请需要经过一系列的规则检查,例如:

  • 身份证校验
  • 黑名单检测
  • 信用评分计算
  • 额度限制校验

这些规则可以按顺序依次处理,或者某个规则失败时中断处理。

3.6.2. API 请求过滤

如在微服务架构中,API 请求经过以下责任链:

  • 身份验证拦截器
  • 参数校验拦截器
  • 权限检查拦截器
  • 日志记录拦截器

3.6.3. 异常处理链

多个异常处理器按顺序处理异常,例如:

  • 数据库异常处理器
  • 网络异常处理器
  • 业务逻辑异常处理器
    责任链可以逐级定位和处理异常。

3.6.4. 广告投放系统

  • 按用户属性(年龄、性别、兴趣)动态匹配投放规则。
  • 若某规则不适用,则传递给下一个规则。

4. 责任链模式示例(Spring)

在 Spring 中使用 责任链模式 并让链上的处理器由 Spring 容器管理,可以通过以下方式实现:利用 Spring 的 @Component 注解 配合 自动注入(@Autowired) 或者通过 @Order 注解 实现责任链的顺序化管理。

4.1. 定义责任链接口

public interface Handler {boolean handle(Request request);
}

每个校验规则实现该接口,handle 方法返回 true 代表校验通过,false 代表校验失败。

4.2. 定义请求对象

@Data
public class Request {private String userId;private int creditScore;private double loanAmount;// 其他字段...// Getter & Setter
}

4.3. 创建具体的处理器

每个处理器(节点)实现 Handler 接口,例如:

4.3.1. 身份校验处理器

@Component
public class IdentityValidationHandler implements Handler {@Overridepublic boolean handle(Request request) {// 假设用户 ID 不能为空if (request.getUserId() == null || request.getUserId().isEmpty()) {System.out.println("身份校验失败");return false;}System.out.println("身份校验通过");return true;}
}

4.3.2. 黑名单检测处理器

@Component
public class BlacklistCheckHandler implements Handler {@Overridepublic boolean handle(Request request) {// 假设用户 "123" 是黑名单用户if ("123".equals(request.getUserId())) {System.out.println("黑名单校验失败");return false;}System.out.println("黑名单校验通过");return true;}
}

4.3.3. 信用评分校验处理器

public class CreditScoreCheckHandler implements Handler {@Overridepublic boolean handle(Request request) {// 假设信用评分不能低于 600if (request.getCreditScore() < 600) {System.out.println("信用评分校验失败");return false;}System.out.println("信用评分校验通过");return true;}
}

4.3.4. 额度检查处理器

@Component
public class LoanAmountCheckHandler implements Handler {@Overridepublic boolean handle(Request request) {// 假设贷款金额不能超过 50 万if (request.getLoanAmount() > 500000) {System.out.println("额度检查失败");return false;}System.out.println("额度检查通过");return true;}
}

4.4. 责任链测试

package com.zhuangxiaoyan.hyxftest.chain;import com.zhuangxiaoyan.hyxftest.HyxfTestApplication;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;/*** chaintest** @author xjl* @version 2024/12/04 19:56**/@SpringBootTest(classes = HyxfTestApplication.class)
public class ChainTest {@Autowiredprivate HandlerChain handlerChain;@Testpublic void chainTest() {handlerChain.process(new Request("122222", 500, 10000));}
}

5. 博文参考

《软件设计模式》

相关文章:

设计模式——Chain(责任链)设计模式

摘要 责任链设计模式是一种行为设计模式&#xff0c;通过链式调用将请求逐一传递给一系列处理器&#xff0c;直到某个处理器处理了请求或所有处理器都未能处理。它解耦了请求的发送者和接收者&#xff0c;允许动态地将请求处理职责分配给多个对象&#xff0c;支持请求的灵活传…...

HarmonyOS(63) ArkUI 自定义占位组件NodeContainer

NodeContainer 1、前言2、NodeContainer和NodeController3、示例代码3.1、创建@Builder3.2、 创建NodeController3.3、 使用NodeCtroller4、NodeContainer的作用5、FrameNode简介6、BuilderNode简介7、参考资料1、前言 在HarmonyOS(62) ArkUI @Reusable组件复用原理讲了组件复…...

Python深度强化学习对冲策略:衍生品投资组合套期保值Black-Scholes、Heston模型分析...

全文链接&#xff1a;https://tecdat.cn/?p38463 本文提出了一个在存在交易成本、市场冲击、流动性约束或风险限制等市场摩擦的情况下&#xff0c;使用现代深度强化学习方法对衍生品投资组合进行套期保值的框架。我们讨论了标准强化学习方法如何应用于非线性奖励结构&#xff…...

【opencv入门教程】2. Point()类用法

文章选自&#xff1a; void Samples::PointFunc() {//输入二维点Point2f point2f(6, 2);cout << "【2维点】p " << point2f << ";\n" << endl;// 输入三维点Point3f point3f(8, 2, 0);cout << "【3维点】p3f "…...

前端导出excel实战(xlsx库和exceljs库)

一. 概览 前端导出excel是比较常见的需求&#xff0c;比如下载excel模板和批量导出excel。目前比较常用的库有xlsx和excel&#xff0c;接下来就着两种方式进行梳理。 二. 下载模板 xlsx库实现&#xff1a; 示例核心代码如下&#xff1a; const excelColumn {details: {ma…...

【附源码】基于环信鸿蒙IM SDK实现一个聊天Demo

项目背景 本项目基于环信IM 鸿蒙SDK 打造的鸿蒙IM Demo&#xff0c;完全适配HarmonyOS NEXT系统&#xff0c;实现了发送消息&#xff0c;添加好友等基础功能。代码开源&#xff0c;功能简洁&#xff0c;如果您有类似开发需求可以参考。 源码地址&#xff1a;https://github.c…...

Python库常用函数-数据分析

Python库常用函数 1.pandas库 &#xff08;1&#xff09;数据读取与写入 读取 CSV 文件&#xff1a; data pd.read_csv(file.csv)读取 Excel 文件&#xff1a; data pd.read_excel(file.xlsx, sheet_nameSheet1)写入 CSV 文件&#xff1a; data.to_csv(new_file.csv, ind…...

汽车EEA架构:架构的简介

1.架构的定义 汽车领域谈论的架构一词&#xff0c;来源于英文单词Architecture。在《系统架构:复杂系统的产品设计与开发》一书中对架构的定义如下:系统架构是一种概念的具象化&#xff0c;是物理或信息功能到形式元素的分配&#xff0c;是系统之内的元素之间的关系与周边环境…...

渗透测试--数据库攻击

这篇文章瘾小生其实想了很久&#xff0c;到底是放在何处&#xff0c;最终还是想着单拎出来总结&#xff0c;因为数据库攻击对我们而言非常重要&#xff0c;而且内容众多。本篇文章将讲述在各位获取数据库权限的情况下&#xff0c;各个数据库会被如何滥用&#xff0c;以及能够滥…...

反向路径转发(RPF)

本文介绍了反向路径转发&#xff08;RPF&#xff09;是如何在FortiGate上实现的。 它还解释了特定于VDOM的CLI设置“config system settings -> set strict-src-check”如何修改RPF行为。 测试场景中使用了以下设置 反向路径过滤器&#xff08;又名RPF&#xff09;是一种安…...

Python 正则表达式常用特殊字符及其含义

以下是 Python 正则表达式常用特殊字符及其含义 的全面整理&#xff0c;涵盖了常见和重要的正则符号&#xff0c;以及它们的示例&#xff0c;适合用来写博客或学习使用&#xff1a; Python 正则表达式常用特殊字符及其含义 1. . (点号) 含义&#xff1a;匹配除换行符 \n 以外…...

Uniapp Android SpringBoot3 对接支付宝支付(最新教程附源码)

Uniapp Android SpringBoot3 对接支付宝支付&#xff08;最新教程附源码&#xff09; 1、效果展示2、后端实现2.1 引入支付宝SDK依赖 pom.xml2.2 配置 application.yml2.3 支付宝相关代码2.3.1 AlipayConfig.java2.3.2 ZfbPayConfig.java2.3.3 支付接口2.3.4 支付回调处理接口&…...

SQL DML 语句

CREATE TABLE classes (ClassID varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 班级ID,ClassName varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 班级名称,TeacherID varchar(20) CHARACTER SET utf8mb4…...

饲料颗粒机全套设备有哪些机器组成

颗粒饲料机主要用于将各种饲料原料&#xff08;如玉米、豆粕、麦麸、鱼粉等&#xff09;进行混合、压制&#xff0c;制成颗粒状的饲料。这种饲料不仅方便储存和运输&#xff0c;还能提高动物的采食效率和饲料利用率。同时&#xff0c;颗粒饲料在加工过程中能灭部分微生物和寄生…...

MySQL事务与锁

定义一个事务向d_eams数据库的student表中插入3条记录&#xff0c;并检验若插入相同的学号&#xff0c;则回滚事务&#xff0c;既插入无效&#xff0c;否则成功提交 delimiter $$ create procedure tr_proc() begindeclare continue handler for sqlstate 23000beginrollback;…...

汽车免拆案例 | 2007款宝马650i车发动机偶尔无法起动

故障现象 一辆2007款宝马650i车&#xff0c;搭载N62B48B发动机&#xff0c;累计行驶里程约为26万km。车主反映&#xff0c;发动机偶尔无法起动&#xff0c;故障频率较低&#xff0c;十几天出现1 次&#xff0c;且故障出现时起动机不工作。 故障诊断  接车后试车&#xff0c;…...

PostgreSQL和Oracle的sql差异

PostgreSQL和Oracle的sql差异 1.rownum &#xff08;1&#xff09;Oracle分页查询使用rownum&#xff0c;PostgreSQL使用limit offset ORACLEPOSTGRESQLselect * from (select rownum r,e.* from emp e where rownum <5) t where r>0;select * from emp limit 5 offset…...

SpringMvc完整知识点二(完结)

SpringMVC获取请求参数 环境准备工作等均省略&#xff0c;可详见快速入门&#xff0c;此处只写非共有部分代码 该部分示例项目SpringMvcThree已上传至Gitee&#xff0c;可自行下载 客户端请求参数的格式为&#xff1a;namevalue&passwordvalue... ... 服务端想要获取请求…...

29 - Java Serializable 序列化

Java的Serializable接口是Java序列化机制的核心&#xff0c;它允许一个对象的状态被转换为字节流&#xff0c;从而可以方便地进行存储或传输。 序列化后的对象可以被写到数据库、存储到文件系统&#xff0c;或者通过网络传输。 要在 Java 中使一个类可序列化&#xff0c;你需要…...

59 基于STM32的烟雾、红外、温湿度检测

所有仿真详情导航: PROTEUS专栏说明-CSDN博客 目录 一、主要功能 二、硬件资源 三、主程序编程 四、资源下载 一、主要功能 基于SMT32F103C8T6单片机,采用DHT11检测温湿度,采用光敏电阻检测光照,采用滑动变阻器分别模拟红外、烟雾,通过OLED显示屏显示,如果湿度过低…...

通过taotoken审计日志追溯api调用详情与安全分析

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 通过Taotoken审计日志追溯API调用详情与安全分析 对于将大模型API集成到业务流程中的团队而言&#xff0c;API调用的可见性与可控性…...

避坑指南:Unity热重载插件内存占用高?可能是Windows Defender在搞鬼

Unity热重载性能优化&#xff1a;解决Windows Defender导致的资源占用问题 当你在Unity开发过程中频繁修改C#代码时&#xff0c;热重载(Hot Reload)功能无疑是提升效率的利器。它能让你在游戏运行状态下即时看到代码修改效果&#xff0c;避免反复重启带来的时间浪费。然而&…...

【避坑指南】VSCode+EIDE+Keil混合开发环境:从零搭建到项目无缝迁移

1. 为什么需要VSCodeEIDEKeil混合开发环境&#xff1f; 作为一名嵌入式开发者&#xff0c;我深知Keil这个老牌IDE在开发效率上的痛点&#xff1a;代码补全弱、界面老旧、多窗口管理混乱。但直接完全迁移到VSCode又面临工程兼容性问题&#xff0c;特别是对传统AC5编译器的支持。…...

WandEnhancer技术解密:如何通过本地化增强重新定义游戏修改体验

WandEnhancer技术解密&#xff1a;如何通过本地化增强重新定义游戏修改体验 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 你是否曾经面对游戏修改工具…...

高效视频帧提取终极指南:为深度学习构建专业数据集

高效视频帧提取终极指南&#xff1a;为深度学习构建专业数据集 【免费下载链接】video2frame Yet another easy-to-use tool to extract frames from videos, for deep learning and computer vision. 项目地址: https://gitcode.com/gh_mirrors/vi/video2frame 在计算机…...

Python自动化股票分析工具:从数据采集到可视化报告全流程实战

1. 项目概述&#xff1a;一个面向个人投资者的自动化股票分析工具如果你和我一样&#xff0c;是个对A股市场有点兴趣&#xff0c;但又没时间天天盯盘的上班族&#xff0c;那你肯定也经历过这种纠结&#xff1a;早上开盘前想看看心仪的几只股票有没有什么异动&#xff0c;结果一…...

Vim-ai插件深度指南:在Vim中无缝集成AI提升开发效率

1. 项目概述&#xff1a;当Vim遇上AI&#xff0c;一场编辑器生产力的革命如果你和我一样&#xff0c;是个在终端里泡了十多年的老Vim用户&#xff0c;那你一定经历过这样的场景&#xff1a;面对一个复杂的函数重构&#xff0c;手指在键盘上飞舞&#xff0c;:s、%s、宏录制轮番上…...

从零构建专属大语言模型:Self-LLM开源项目全流程实践指南

1. 项目概述与核心价值最近在开源社区里&#xff0c;一个名为datawhalechina/self-llm的项目引起了我的注意。乍一看&#xff0c;这像是一个关于大语言模型&#xff08;LLM&#xff09;的仓库&#xff0c;但“self”这个前缀又让人浮想联翩。经过一段时间的深入研究和实践&…...

大气层系统深度解析:构建Switch的六层数字防护体系

大气层系统深度解析&#xff1a;构建Switch的六层数字防护体系 【免费下载链接】Atmosphere-stable 大气层整合包系统稳定版 项目地址: https://gitcode.com/gh_mirrors/at/Atmosphere-stable 在Nintendo Switch的定制固件生态中&#xff0c;Atmosphere&#xff08;大气…...

避坑指南:uniapp在微信小程序中调用相机和人脸识别的权限与兼容性问题

Uniapp微信小程序相机与人脸识别开发避坑指南 微信小程序作为轻量级应用平台&#xff0c;其相机与人脸识别功能在金融、社交、教育等领域应用广泛。然而&#xff0c;当开发者使用Uniapp这一跨平台框架进行微信小程序开发时&#xff0c;往往会遇到各种兼容性和权限问题。本文将深…...