【知识科普】设计模式之-责任链模式
这里写自定义目录标题
- 概述
- 责任链模式的详细描述
- 责任链模式的使用场景
- 使用场景举例
- 1. 审批流程
- 示例:
- 2. 过滤器链
- 示例:
- 3. 事件处理系统
- 示例:
- 4. 插件系统
- 示例:
- Java代码示例及注释
- 代码解释
概述
责任链模式的详细描述
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象按照一定顺序处理请求,并且每个对象都有机会选择是否处理该请求或将其传递给下一个对象。这种模式将请求的发送者和接收者解耦,提供了更大的灵活性和可扩展性。
在责任链模式中,有两个主要角色:
- 抽象处理者(Handler):定义了处理请求的接口,并持有对下一个处理者的引用。
- 具体处理者(ConcreteHandler):实现了抽象处理者接口,负责实际处理请求的逻辑。
当一个请求从链首开始传递时,每个处理者都有机会处理该请求,直到其中一个处理者能够处理为止。如果当前处理者不能处理该请求,它会将请求传递给下一个处理者。这样,请求发送者无需知道具体的处理对象,只需将请求发送到责任链上即可。
责任链模式的使用场景
责任链模式通常用于以下场景:
- 多个对象可以处理同一请求:当系统中存在多个对象可以处理同一请求时,可以使用责任链模式将这些对象组织成一条链,并动态地选择处理者。
- 处理者之间的顺序不确定:当处理请求的对象之间的顺序不确定或需要动态调整时,责任链模式可以灵活地组织处理者的顺序。
- 请求处理具有多种可能性:当请求的处理结果有多种可能性,且这些可能性需要在运行时确定时,责任链模式可以根据请求的内容和当前处理者的逻辑来决定如何处理请求。
使用场景举例
责任链模式的使用场景通常涉及多个对象可以处理同一请求,且这些对象之间的处理顺序或责任分配可能在运行时动态变化的情况。以下是一些具体的使用场景示例:
1. 审批流程
在一个企业中,可能有多个层级的审批人员(如部门经理、总监、副总裁、总裁等)需要审批某个项目或请求。每个审批人员都有自己的审批权限和规则。使用责任链模式,可以将这些审批人员组织成一条链,当请求提交时,它会依次传递给每个审批人员,直到找到能够批准该请求的人员为止。
示例:
- 抽象审批者:定义了审批请求的方法。
- 具体审批者(如部门经理、总监等):实现了抽象审批者的方法,并根据自己的权限和规则决定是否批准请求或传递给下一个审批者。
2. 过滤器链
在Web开发中,经常需要对请求和响应进行过滤,如身份验证、日志记录、输入验证等。使用责任链模式,可以将这些过滤器组织成一条链,每个过滤器都有机会处理请求或响应,并在必要时将控制权传递给下一个过滤器。
示例:
- 抽象过滤器:定义了处理请求和响应的方法。
- 具体过滤器(如身份验证过滤器、日志记录过滤器等):实现了抽象过滤器的方法,并根据自己的逻辑处理请求或响应。
3. 事件处理系统
在一些应用程序中,可能需要处理各种类型的事件,如用户点击、键盘输入、系统错误等。使用责任链模式,可以将这些事件的处理程序组织成一条链,每个处理程序都有机会处理事件,并在必要时将事件传递给下一个处理程序。
示例:
- 抽象事件处理器:定义了处理事件的方法。
- 具体事件处理器(如用户点击处理器、键盘输入处理器等):实现了抽象事件处理器的方法,并根据事件类型和自己的逻辑处理事件。
4. 插件系统
在一些软件框架或平台中,可能允许用户或开发者添加自定义的插件来扩展功能。使用责任链模式,可以将这些插件组织成一条链,并在运行时动态地加载和调用它们。每个插件都有机会处理请求或提供自己的功能,并在必要时将控制权传递给下一个插件。
示例:
- 抽象插件:定义了插件需要实现的方法。
- 具体插件:实现了抽象插件的方法,并提供了自定义的功能或处理逻辑。
这些场景展示了责任链模式在动态责任分配、请求处理和事件处理方面的灵活性。通过组织成链式的处理者,责任链模式允许系统在运行时动态地决定由哪个对象处理请求,从而提高了系统的可扩展性和可维护性。
Java代码示例及注释
以下是一个使用Java实现责任链模式的示例代码,以及对应的注释:
// 定义请求类
class Request {private String content;public Request(String content) {this.content = content;}public String getContent() {return content;}
}// 定义抽象处理者接口
interface Handler {void handleRequest(Request request);
}// 具体处理者A,实现Handler接口
class ConcreteHandlerA implements Handler {private Handler successor;public void setSuccessor(Handler successor) {this.successor = successor;}@Overridepublic void handleRequest(Request request) {if (request.getContent().contains("A")) {System.out.println("ConcreteHandlerA: Handling the request");} else if (successor != null) {successor.handleRequest(request);}}
}// 具体处理者B,实现Handler接口
class ConcreteHandlerB implements Handler {private Handler successor;public void setSuccessor(Handler successor) {this.successor = successor;}@Overridepublic void handleRequest(Request request) {if (request.getContent().contains("B")) {System.out.println("ConcreteHandlerB: Handling the request");} else if (successor != null) {successor.handleRequest(request);}}
}// 客户端代码
public class Main {public static void main(String[] args) {// 创建处理者对象Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();// 设置处理者链handlerA.setSuccessor(handlerB);// 创建请求对象Request request1 = new Request("This is requestA");Request request2 = new Request("This is requestB");Request request3 = new Request("This is requestC");// 处理请求handlerA.handleRequest(request1); // ConcreteHandlerA: Handling the requesthandlerA.handleRequest(request2); // ConcreteHandlerB: Handling the requesthandlerA.handleRequest(request3); // 无输出,因为两个处理者都不处理requestC}
}
代码解释
- Request类:表示一个请求,包含请求的内容。
- Handler接口:定义了处理请求的接口,所有具体处理者都需要实现这个接口。
- ConcreteHandlerA和ConcreteHandlerB类:实现了Handler接口,分别处理包含"A"和"B"的请求内容。如果请求内容不匹配,它们会将请求传递给下一个处理者。
- Main类:客户端代码,创建处理者对象并设置处理者链,然后创建请求对象并调用处理请求的方法。
在这个示例中,当发送一个包含"A"的请求时,ConcreteHandlerA会处理该请求;当发送一个包含"B"的请求时,ConcreteHandlerB会处理该请求;如果发送一个包含"C"的请求,则两个处理者都不会处理该请求,因为没有处理者包含处理"C"的逻辑。
相关文章:
【知识科普】设计模式之-责任链模式
这里写自定义目录标题 概述责任链模式的详细描述责任链模式的使用场景 使用场景举例1. 审批流程示例:2. 过滤器链示例:3. 事件处理系统示例:4. 插件系统示例: Java代码示例及注释代码解释 概述 责任链模式的详细描述 责任链模式…...
fiddler安卓雷电模拟器配置踩坑篇
一、fiddler端配置 和网页版fiddler一样,需要首先再本机安装证书,可以参考我之前的fiddler浏览器配置文章,前期操作一致: 此处需要注意的是connections里面需要勾选allow remote这个选项,这个主要是为了后来再安卓模拟…...
机器学习5-多元线性回归
多元线性回归 主要了解多元线性回归的原理以及数学推导。 只有损失函数是凸函数才能确认是最优解,极值不一定是最优解 判定凸函数的方式非常多,其中一个方法是看黑塞矩阵是否是半正定的。 黑塞矩阵(hessian matrix)是由目标函数在…...
Linux kernel 堆溢出利用方法(三)
前言 本文我们通过我们的老朋友heap_bof来讲解Linux kernel中任意地址申请的其中一种比赛比较常用的利用手法modprobe_path(虽然在高版本内核已经不可用了但ctf比赛还是比较常用的)。在通过两道道近期比赛的赛题来讲解。 Arbitrary Address Allocation…...
对于GC方面,在使用Elasticsearch时要注意什么?
大家好,我是锋哥。今天分享关于【对于GC方面,在使用Elasticsearch时要注意什么?】面试题。希望对大家有帮助; 对于GC方面,在使用Elasticsearch时要注意什么? 1000道 互联网大厂Java工程师 精选面试题-Java…...
Xilinx PCIe高速接口入门实战(一)
引言:本文对Xilinx 7 Series Intergrated Block for PCI Express PCIe硬核IP进行简要介绍,主要包括7系列FPGA PCIe硬核资源支持、三IP硬核差异、PCIe硬核资源利用等相关内容。 1. 概述 1.1 7系列FPGA PCIe硬件资源支持 7系列FPGA对PCIe接口最大支持如…...
Flume 监控配置和实践
要解释 Flume 的监控机制,需要了解 Flume 是如何设计其监控架构的,以及如何将性能指标暴露给用户或集成工具。下面我将详细分解 Flume 的监控机制,从基础架构、实现原理到源码解析,并提供非专业人也能理解的通俗解释。 Flume 的监…...
深度学习基础1
目录 1. 深度学习的定义 2.神经网络 2.1. 感知神经网络 2.2 人工神经元 2.2.1 构建人工神经元 2.2.2 组成部分 2.2.3 数学表示 2.2.4 对比生物神经元 2.3 深入神经网络 2.3.1 基本结构 2.3.2 网络构建 2.3.3 全连接神经网络 3.神经网络的参数初始化 3.1 固定值初…...
《FPGA开发工具》专栏目录
《FPGA开发工具》专栏目录 1.Vivado开发 1.1使用相关 Vivado工程创建、仿真、下载与固化全流程 Vivado工程快速查看软件版本与器件型号 Vivado IP核的快速入门 官方手册和例程 Vivado中对已调用IP核的重命名 Vivado中增加源文件界面中各选项的解释 Vivado IP中Generate…...
李春葆《数据结构》-查找-课后习题代码题
一:设计一个折半查找算法,求查找到关键字为 k 的记录所需关键字的比较次数。假设 k 与 R[i].key 的比较得到 3 种情况,即 kR[i].key,k<R[i].key 或者 k>R[i].key,计为 1 次比较(在教材中讨论关键字比…...
【Git】:分支管理
目录 理解分支 创建分支 切换分支 合并分支 删除分支 合并冲突 分支管理策略 快进合并 正常合并 bug 分支 总结 理解分支 在版本控制系统中,分支是一条独立的开发线路。它允许开发者从一个主要的代码基线(例如master分支)分离出来…...
C、C++ 和 Java的区别
C、C 和 Java 是三种广泛使用的编程语言,它们各有特点,适合不同的应用场景。以下从多个角度对它们的区别进行分析: 基础特性 特性CCJava语言类型过程式编程语言过程式 面向对象编程语言纯面向对象编程语言(也支持过程式&#x…...
【Python-Open3D学习笔记】005Mesh相关方法
TriangleMesh相关方法 文章目录 TriangleMesh相关方法1. 查看mesh三角形面信息2. 可视化三角形3. 上采样4. 计算mesh形成的面积和体积 1. 查看mesh三角形面信息 def view_hull_triangles(hull: o3d.geometry.TriangleMesh):"""查看mesh三角形面信息(…...
js原型、原型链和继承
文章目录 一、原型1、prototype2、constructor 二、原型链1、字面量原型链2、字面量继承3、构造函数的原型链4、Object.create5、Object.setPrototypeOf 三、继承1、构造函数继承2、原型链继承3、组合继承 四、常见链条1、Function2、Object.prototype 继承是指将特性从父代传递…...
团队自创【国王的魔镜-2】
国王的魔镜-2 题目描述 国王有一个魔镜,可以把任何接触镜面的东西变成原来的两倍——只是,因为是镜子嘛,增加的那部分是反的。比如一条项链,我们用AB来表示,不同的字母表示不同颜色的珍珠。如果把B端接触镜面的话&am…...
c++编程玩转物联网:使用芯片控制8个LED实现流水灯技术分享
在嵌入式系统中,有限的GPIO引脚往往限制了硬件扩展能力。74HC595N芯片是一种常用的移位寄存器,通过串行输入和并行输出扩展GPIO数量。本项目利用树莓派Pico开发板与74HC595N芯片,驱动8个LED实现流水灯效果。本文详细解析项目硬件连接、代码实…...
【Jenkins】docker 部署 Jenkins 踩坑笔记
文章目录 1. docker pull 超时2. 初始化找不到 initialAdminPassword 1. docker pull 超时 docker pull 命令拉不下来 docker pull jenkins/jenkins:lts-jdk17 Error response from daemon: Get "https://registry-1.docker.io/v2/": 编辑docker配置 sudo mkdir -…...
Unreal Engine使用Groom 打包后报错
Unreal Engine使用Groom打包后报错 版本5.4.4 blender 4.2.1 项目头发用了groom,运行后报错 错误: Assertion failed: Offset BytesToRead < UncompressedFileSize && Offset > 0 [File:E:\UnrealEngine-5.4.4-release\Engine\Source\R…...
嵌入式QT学习第3天:UI设计器的简单使用
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 Qt Creator 里自带的 Qt Designer,使用 Qt Designer 比较方便的构造 UI 界 面。 在 UI 文件添加一个按钮 左边找到 Push Button,然后拖拽到中…...
【连接池】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...
构建个人技能知识库:从Markdown管理到自动化实践
1. 项目概述:一个技能库的诞生与价值最近在整理个人知识体系时,我一直在思考一个问题:如何将那些零散的、跨领域的“技能点”系统化地管理起来,形成一个可以持续迭代、随时取用的个人工具箱?这不仅仅是写一份简历上的技…...
Proteus仿真入门:手把手教你用51单片机点亮共阳数码管(附完整代码与电路图)
Proteus仿真入门:51单片机驱动共阳数码管全流程解析 第一次接触单片机仿真时,看着那些闪烁的数码管总觉得神奇又遥远。记得我大三那年,为了完成课程设计,在实验室熬了三个通宵才让数码管显示出正确的数字。今天,我们就…...
从零搭建AI增强型第二大脑:NotebookLM+Obsidian+Dataview三体联动,7天知识处理效率提升3.8倍
更多请点击: https://intelliparadigm.com 第一章:NotebookLM与Obsidian整合的底层逻辑与价值定位 NotebookLM 与 Obsidian 的整合并非简单插件叠加,而是基于“语义增强型知识工作流”的范式迁移。其底层逻辑根植于双引擎协同:No…...
如何快速解密QMC音频文件:qmc-decoder完整使用指南
如何快速解密QMC音频文件:qmc-decoder完整使用指南 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder 你是否遇到过从音乐平台下载的歌曲无法在其他播放器播放的情…...
Rails AI上下文管理引擎:构建LLM友好的业务操作上下文
1. 项目概述:一个AI驱动的Rails上下文管理引擎最近在重构一个历史悠久的Rails项目时,我遇到了一个典型的老问题:业务逻辑散落在各个控制器、模型和Service对象里,一个简单的用户操作背后要追踪七八个文件才能理清完整的上下文。更…...
Hyprland截图方案:Wayland下高效截图工具配置与优化指南
1. 项目概述与核心价值最近在折腾Hyprland窗口管理器,发现一个痛点:截图。系统自带的工具要么功能单一,要么和Hyprland的Wayland环境配合不佳,用起来总感觉差点意思。直到我发现了nikolai2038/hyprland-screenshoter这个项目&…...
动态加载数据库微信支付配置
在Java后端应用中,动态加载存储在数据库中的微信支付配置,是实现多商户、多环境支付或配置热更新的核心需求。这避免了将API密钥、商户号等敏感信息硬编码在配置文件或代码中,提升了系统的灵活性与安全性。核心实现思路是:构建一个…...
本地AI网关实战:统一管理多模型服务,实现智能路由与成本控制
1. 项目概述:一个本地化的AI网关如果你正在同时使用多个AI模型服务商,比如OpenAI、Anthropic、Google Gemini,或者还在本地运行着Ollama、vLLM这样的模型,那你一定体会过那种切换的繁琐。每个客户端、每个脚本都要配置不同的API密…...
AI Agent技能生成器:从零创建精准高效的SKILL.md文件
1. 项目概述:一个为AI Agent生成“技能说明书”的元技能如果你和我一样,经常在Claude Code、Cursor或者Codex这类AI编程助手工具里折腾,想让它帮你处理一些特定的、重复性的开发任务,那你肯定对“技能”(Skill…...
用STM32的TIM1和GPIO中断,手把手教你实现带霍尔BLDC的平稳启动与调速(附PID代码)
STM32实战:基于霍尔传感器的BLDC电机六步换相与PID调速全解析 在工业自动化、无人机和机器人等领域,无刷直流电机(BLDC)凭借其高效率、长寿命和低噪音特性成为首选驱动方案。本文将深入探讨如何利用STM32的TIM1高级定时器和GPIO中断实现带霍尔传感器的BL…...
