设计模式行为型——责任链模式
目录
什么是责任链模式
责任链模式的实现
责任链模式角色
责任链模式类图
责任链模式举例
责任链模式代码实现
责任链模式的特点
优点
缺点
使用场景
注意事项
实际应用
什么是责任链模式
责任链模式(Chain of Responsibility Pattern)又叫职责链模式,是一种行为型设计模式,它通过建立一个对象链来依次处理请求,将请求的发送者和接收者解耦,并允许多个对象都有机会处理请求。其目的是为了解决请求端与实现端的解耦。其实现过程类似递归调用。责任链模式的核心是定义责任链节点的接口以及节点之间的关系,它允许动态的增加和修改责任链中的节点。
责任链模式的实现
责任链模式角色
抽象处理者(Handler):定义了处理请求的接口,并维护一个指向下一处理者的引用。通常包含一个处理方法 handleRequest()。
具体处理者(ConcreteHandler):实现了抽象处理者接口,对请求进行具体处理,如果自身无法处理,则将请求转发给下一处理者。
责任链模式类图
责任链模式举例
以公司采购审批为例,不同金额的采购需要不同人员的审批,比如20000以下需要项目经理审批,20000-50000需要部门经理审批,50000以上需要总经理审批。此时我们把审批流程可以看作一个审批责任链条,进而可以使用责任链模式。
责任链模式代码实现
实体请求类
package com.common.demo.pattern.chain;import java.math.BigDecimal;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 实体请求类* @date 2023/07/27 13:35:41*/
public class PurchaseReq {/*** 请求类型*/private int type;/*** 金额*/private BigDecimal price;/*** 用途*/private String purpose;public PurchaseReq(int type, BigDecimal price, String purpose) {this.type = type;this.price = price;this.purpose = purpose;}public int getType() {return type;}public void setType(int type) {this.type = type;}public BigDecimal getPrice() {return price;}public void setPrice(BigDecimal price) {this.price = price;}public String getPurpose() {return purpose;}public void setPurpose(String purpose) {this.purpose = purpose;}@Overridepublic String toString() {return "PurchaseReq{" +"type=" + type +", price=" + price +", purpose=" + purpose +'}';}
}
抽象处理者角色
package com.common.demo.pattern.chain;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 抽象审批者处理类, 抽象处理者角色* @date 2023/07/27 13:44:42*/
public abstract class Approver {Approver approver;String name;public Approver() {}public Approver(String name) {this.name = name;}/*** 下一个处理者*/public void setApprover(Approver approver) {this.approver = approver;}/*** 处理审批请求的方法,得到一个请求,处理是子类实现*/public abstract void process(PurchaseReq purchaseReq);}
具体处理者角色
package com.common.demo.pattern.chain;import java.math.BigDecimal;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 项目经理 具体审批者* @date 2023/07/27 13:49:16*/
public class ProjectManager extends Approver {public ProjectManager(String name) {super(name);}@Overridepublic void process(PurchaseReq purchaseReq) {// 小于 5000 项目经理审批即可if (purchaseReq.getPrice().compareTo(new BigDecimal(5000)) == -1) {System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,审批终结!");} else {System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,进入下一级审批!");approver.process(purchaseReq);}}
}
package com.common.demo.pattern.chain;import java.math.BigDecimal;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 部门经理 具体审批者* @date 2023/07/27 13:49:48*/
public class DepartmentManager extends Approver{public DepartmentManager(String name) {super(name);}@Overridepublic void process(PurchaseReq purchaseReq) {// 小于 20000 大于 5000, 部门经理审批即可if(purchaseReq.getPrice().compareTo(new BigDecimal(20000))==-1){System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,审批终结!");} else {System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,进入下一级审批!");approver.process(purchaseReq);}}
}
package com.common.demo.pattern.chain;import java.math.BigDecimal;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 总经理 具体审批者* @date 2023/07/27 13:50:45*/
public class GeneralManager extends Approver {public GeneralManager(String name) {super(name);}@Overridepublic void process(PurchaseReq purchaseReq) {// 大于 20000 ,总经理审批if (new BigDecimal(20000).compareTo(purchaseReq.getPrice()) == -1) {System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,审批终结!");} else {System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,进入下一级审批!");approver.process(purchaseReq);}}
}
测试类
package com.common.demo.pattern.chain;import java.math.BigDecimal;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 测试类* @date 2023/07/27 14:23:01*/
public class Test {public static void main(String[] args) {PurchaseReq purchaseRequest1 = new PurchaseReq(1, new BigDecimal(1000), "购买饮水机");PurchaseReq purchaseRequest2 = new PurchaseReq(2, new BigDecimal(6000), "购买打印机");PurchaseReq purchaseRequest3 = new PurchaseReq(2, new BigDecimal(30000), "购买苹果笔记本办公");ProjectManager projectManager = new ProjectManager("项目经理");DepartmentManager departmentManager = new DepartmentManager("部门经理");GeneralManager generalManager = new GeneralManager("总经理");//设置下一级处理人projectManager.setApprover(departmentManager);departmentManager.setApprover(generalManager);//都从项目经理开始处理projectManager.process(purchaseRequest1);projectManager.process(purchaseRequest2);projectManager.process(purchaseRequest3);}
}
测试截图
责任链模式的特点
优点
- 降低耦合度:将请求和处理分开,请求的发送者和接收者各个组件间完全解耦。
- 简化了对象:使得对象不需知道链的结构,请求者无需知道接受者,无需知道其如何处理。
- 增强灵活性:通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任对象。
- 新增便捷性:增加新的请求处理类很方便。
缺点
- 因为只关心自己内部实现,不关心链内部结构,开发调试会比较麻烦。不容易确认调用的哪一个实现。
- 增加系统的资源消耗。因为链式调用,可能会进行很多次判断,因为每个实现都会判断是否能够处理该请求,不能处理则调用下一个,增加了系统开销。
- 不能保证请求被消化,因其特殊特性,在处理之前会判断是否能够处理,如果每一个链都不能处理,那么该请求无法被消化。
使用场景
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态指定一组对象处理请求。
注意事项
- 合理设计责任链的节点:责任链模式的核心是将任务分解为一系列的处理节点,每个节点都有机会处理任务或将其传递给下一个节点。在设计责任链节点时,需要根据实际情况合理地划分节点责任,确保每个节点的功能清晰、独立、可扩展,并且能够按需组合形成不同的责任链。
- 灵活配置责任链:责任链模式支持动态配置责任链,也就是可以在运行时通过添加、移除或修改节点来构建不同的责任链。这种灵活性可以根据实际需求动态调整责任链的结构和顺序,但也需要注意避免责任链过长、过于复杂,以及节点的重叠或缺失等问题。
- 节点的执行顺序:责任链模式中,每个节点都有机会处理任务,但处理的顺序是非常重要的。在设计责任链时,需要仔细考虑节点的执行顺序,确保任务能够按照预期的流程依次经过每个节点,同时避免出现死循环或执行顺序混乱等问题。
- 避免责任链的滥用:责任链模式可以很好地解耦请求发送者和接收者之间的关系,但也容易被滥用。在应用责任链模式时,需要审慎选择,确保责任链模式能够带来真正的价值,而不是增加复杂性或降低代码可维护性。
- 错误处理机制:在责任链模式中,如果没有合适的节点处理任务,任务可能会无法得到处理或处理结果不符合预期。因此,在设计责任链时,需要考虑错误处理机制,例如设置默认处理节点、定义异常处理策略等,以确保任务能够得到妥善处理,并且在发生异常时能够及时进行处理和反馈。
实际应用
- Spring框架中的拦截器:拦截器是Spring框架中的一种常见组件,它可以在请求处理前后进行一些额外的处理,例如身份验证、日志记录、权限控制等。拦截器就是利用了责任链模式来将多个处理对象构成一条拦截器链,然后逐个处理请求。Spring框架提供了很多拦截器,例如HandlerInterceptor、WebRequestInterceptor等。
- Servlet中的过滤器:Servlet中的过滤器也是一种常见的使用责任链模式的场景。过滤器可以在请求处理前后进行一些额外的处理,例如安全认证、数据预处理、异常处理等。
- Java 8中的Lambda表达式:Java 8中的Lambda表达式可以看作是一种函数式接口,它利用责任链模式来组合、封装和传递函数对象。Lambda表达式可以通过链式结构形成一个函数的序列,然后按顺序逐个执行这些函数并返回结果,从而可以在Java中实现函数式编程。
- Netty中的处理器Pipeline:Netty是一种基于事件驱动的网络通信框架,它利用责任链模式和事件监听机制来处理请求。Netty中的处理器Pipeline是一条处理请求的链,该链中的每个处理器都可以对请求进行处理和传递,从而形成一个完整的事件处理流程。
更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)
相关文章:

设计模式行为型——责任链模式
目录 什么是责任链模式 责任链模式的实现 责任链模式角色 责任链模式类图 责任链模式举例 责任链模式代码实现 责任链模式的特点 优点 缺点 使用场景 注意事项 实际应用 什么是责任链模式 责任链模式(Chain of Responsibility Pattern)又叫职…...
Xamarin.Android中Intent的使用
目录 1、说明2、使用方法2.1 常用方法2.2 调用系统应用 3、参考资料 1、说明 在Android开发中常常会用到Intent进行不同活动启动,整理资料如下 2、使用方法 2.1 常用方法 1、一般情况而言,都是使用如下的方式进行调用 Intent intent new Intent(th…...

matplotlib绘制方波圆周分解动画
1 方波的圆周分解 在学习傅里叶变换的时候,有一个经典的示例是方波的分解。我们知道,方波可以分解为无数个正弦波的叠加。而正弦波,又可以看作是圆周运动在一条直线上的投影。当时为了理解这个事情,恐怕大家也花了不少时间。 学…...
vue3+ts 实现枚举
首先 index.ts 中定义枚举 export const fruit [{key:1,name:苹果,},{key:11,name:草莓},{key:5,name:香蕉,},{key:51,name:葡萄,},{key:6,name:橙子},{key:7,name:哈密瓜},{key:10,name:西瓜}, ]; 接口返给的数据是一个对象 feeMap{ 1:200, 2&…...

【Python】5分钟了解11个最佳的Python编译器和解释器
11个最佳Python编译器和解释器 1. Brython2. Pyjs3. WinPython4. Skulpt5. Shed Skin6. Active Python7. Transcrypt8. Nutika9. Jython10. CPython11. IronPython结论原文链接 Python是一门初学者的编程语言。它是一种高级语言,非常灵活、解释性和面向对象的语言。…...

如何安装、部署、启动Jenkins
一、测试环境 Linux系统 Centos 7 二、安装步骤: 1、安装jdk 我安装的是jdk8,此处就不多说了,自己百度哈,很简单 2、安装jenkins 首先依次执行如下三个命令: 2.1、导入镜像: [rootcentos7 ~]# sudo …...
sqlalchemy flask长时间未使用 导致数据库连接失效
临时解决方案:在正式运行定时任务之前,先跑一个session.query(),相当于唤醒连接。 参考 https://blog.csdn.net/sinat_42483341/article/details/103723691...
Ubuntu 20.04 系统或图像界面卡死或完全无响应处理方法
Ubuntu 20.04 系统或图像界面卡死或完全无响应处理方法 问题背景无需重启方法安全重启方法 问题背景 Ubuntu 20.04在安装驱动程序时系统突然无响应,终端也无法运行;考虑到尽量不破坏系统,不希望强制上下电重启机器,以免损坏文件系…...

Linux编辑器 - vim使用
1.vim的基本概念 Vim是一个广泛使用的文本编辑器,它是在Unix和Linux系统中常用的命令行文本编辑器之一。 vim的主要三种模式 ( 其实有好多模式,目前掌握这 3 种即可 ), 分别是 命令模式 ( command mode )、 插入模式 ࿰…...
【Windows】磁盘快捷修复
【Windows】磁盘快捷修复 1、背景2、关于Chkdsk3、示例 1、背景 前段时间使用U盘拷贝文件过程中,突然发现U盘无法读取了,U盘里面存储的数据也无法获取。 然后使用windows系统的chkdsk命令进行修复。 chkdsk全称:checkdisk,即磁盘…...

Java 线程的多种状态
前言 在前文中详细介绍了线程的启动、中断、休眠、等待。本文详细介绍线程的多种状态。 获取线程的当前状态代码是: 线程对象.getState(); 目录 前言 一、NEW 二、RUNNABLE 三、BLOCKED 四、WAITNG 五、TIMED_WAITNG 六、TERMINATED 结语 一、NEW Thread 对…...

AI绘画| 迪士尼风格|可爱头像【附Midjourney提示词】
Midjourney案例分享 图片预览 迪士尼风格|可爱头像 高清原图及关键词Prompt已经放在文末网盘,需要的自取 在数字艺术的新时代,人工智能绘画已经迅速崭露头角。作为最先进的技术之一,AI绘画结合了艺术和科学,开启了一…...

【浪费了我两个小时时间】Microsoft store无法加载页面0x80131500
绕的圈,踩的坑 谷歌搜索, newbing搜索都叫我清理缓存,重新安装等方法。 还被这篇文章误导了一下:微软应用商店错误代码0x80072EFD怎么办?(已解决) 加上重启电脑各种试不行。 最后想到要去改代…...

【动态规划】子序列系列
文章目录 动态规划(子序列系列)1. 最长递增子序列2. 摆动序列3. 最长递增子序列的个数4. 最长数对链5. 最长定差子序列6. 最长的斐波那契子序列的长度7. 最长等差数列8. 等差数列划分 || - 子序列 动态规划(子序列系列) 1. 最长递…...

URL存储解锁数据管理的新思路,重新定义数据传输与共享(@vue/repl)
Thinking系列,旨在利用10分钟的时间传达一种可落地的编程思想。 近日,在了解 vue/repl 相关内容,其通过 URL 进行数据存储,感觉思路惊奇,打开了新方式。 首先,通过 URL 存储最大的便利是:无需服…...
matlab程序中文乱码
不同版本的matlab共存在GBK(即,ANSI)和UTF-8两种编码方式,因此可能会出现乱码问题。 第一步:在matlab的命令行窗口输入指令,查看当前编码方式 feature(locale) 第二步:用Notepad打开文件&…...

【计算机视觉|语音分离】期望在嘈杂环境中聆听:一个用于语音分离的不依赖于讲话者的“音频-视觉模型”
本系列博文为深度学习/计算机视觉论文笔记,转载请注明出处 标题:Looking to Listen at the Cocktail Party: A Speaker-Independent Audio-Visual Model for Speech Separation 链接:Looking to listen at the cocktail party: a speaker-in…...
curl 介绍和使用
文章目录 一、介绍1.1 curl 介绍1.2 curl 参数介绍1.3 类似Curl的工具和库 二、使用2.1 curl 下载2.2 curl 示例用法2.3 curl命令使用digest方式验证用户 一、介绍 1.1 curl 介绍 官网:https://curl.se/GitHub源码:https://github.com/curl/curl Curl…...
5、VMWARE安装、MobaXterm SSH连接 、Ubuntu xrdp安装使用
以下是在VMware中安装Ubuntu 22.04的详细步骤: 下载Ubuntu 22.04镜像文件: 前往Ubuntu官方网站或其他可信来源,下载Ubuntu 22.04的镜像文件(.iso格式)。 创建虚拟机: 打开VMware Workstation软件…...
Docker dockerfile 案例:centos 支持 vim
创建一个 centos 容器,容器内默认是不支持使用 vim 指令的,只能使用 vi 指令。(附:Dockerfile 语法与指令) 但想在创建 centos 容器后就支持 vim 指令,需要自定义 centos,编写 dockerfile&…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...