Go和Java实现责任链模式
Go和Java实现责任链模式
下面通过一个审批流程的案例来说明责任链模式的使用。
1、责任链模式
责任链模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这
种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的
请求传给下一个接收者,依此类推。
-
意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且
沿着这条链传递请求,直到有对象处理它为止。
-
主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细
节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
-
何时使用:在处理消息的时候以过滤很多道。
-
如何解决:拦截的类都实现统一接口。
-
关键代码:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向
谁传递之前 set 进去。
-
应用实例:1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡。 3、JAVA WEB 中 Apache Tomcat 对 Encoding
的处理,Struts2 的拦截器,jsp servlet 的 Filter。
-
优点:1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责
任。 4、增加新的请求处理类很方便。
-
缺点:1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能
会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。
-
使用场景:1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明
确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求。
-
注意事项:在 JAVA WEB 中遇到很多应用。
-
适用性:
有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
你在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
可处理一个请求的对象集合应被动态指定。
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一个链,并随着
这条链传递该请求,直到有一个对象处理它为止。这一模式的想法是,给多个对象处理一个请求的机会,从而解耦
发送者和接受者。
2、Go实现责任链模式1
package chainofresponsibility// ========== 定义一个处理请求的接口Request ==========
type Request interface {Processing()
}
package chainofresponsibilityimport "fmt"// ========== 离职DimissionRequest ==========
type DimissionRequest struct {
}func (dimissionRequest *DimissionRequest) Processing() {fmt.Println("处理离职!")
}
package chainofresponsibilityimport "fmt"// ========== 请假LeaveRequest ==========
type LeaveRequest struct {
}func (LeaveRequest *LeaveRequest) Processing() {fmt.Println("处理请假!")
}
package chainofresponsibilityimport "fmt"// ========== 加薪AddMoneyRequest ==========
type AddMoneyRequest struct {
}func (addMoneyRequest *AddMoneyRequest) Processing() {fmt.Println("处理加薪!")
}
package chainofresponsibility// 处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理请求,否则将该请求转发给它的后继者
// ========== RequestHandle ==========
type RequestHandle interface {HandleRequests(Request)Next(RequestHandle)
}
package chainofresponsibilityimport "fmt"// ========== HRRequestHandle ==========
type HRRequestHandle struct {requestHandle RequestHandle
}func (hRRequestHandle *HRRequestHandle) HandleRequests(request Request) {if req, ok := request.(*DimissionRequest); ok {fmt.Println("要离职,人事审批!")req.Processing()}fmt.Println("请求完成!")
}func (hRRequestHandle *HRRequestHandle) Next(requestHandle RequestHandle) {hRRequestHandle.requestHandle = requestHandle
}
package chainofresponsibilityimport "fmt"// ========== PMRequestHandle ==========
type PMRequestHandle struct {requestHandle RequestHandle
}func (pMRequestHandle *PMRequestHandle) HandleRequests(request Request) {if req, ok := request.(*AddMoneyRequest); ok {fmt.Println("要加薪,项目经理审批!")req.Processing()} else {pMRequestHandle.requestHandle.HandleRequests(request)}
}func (pMRequestHandle *PMRequestHandle) Next(requestHandle RequestHandle) {pMRequestHandle.requestHandle = requestHandle
}
package chainofresponsibilityimport "fmt"// ========== TLRequestHandle ==========
type TLRequestHandle struct {requestHandle RequestHandle
}func (tLRequestHandle *TLRequestHandle) HandleRequests(request Request) {if req, ok := request.(*LeaveRequest); ok {fmt.Println("要请假,项目组长审批!")req.Processing()} else {tLRequestHandle.requestHandle.HandleRequests(request)}
}func (tLRequestHandle *TLRequestHandle) Next(requestHandle RequestHandle) {tLRequestHandle.requestHandle = requestHandle
}
package mainimport ("fmt". "proj/chainofresponsibility"
)func main() {hr := HRRequestHandle{}pm := PMRequestHandle{}tl := TLRequestHandle{}tl.Next(&pm)pm.Next(&hr)fmt.Println("===========")// 人事处理离职请求tl.HandleRequests(&DimissionRequest{})fmt.Println("===========")// 项目经理处理加薪请求tl.HandleRequests(&AddMoneyRequest{})fmt.Println("========")// 组长处理请假请求tl.HandleRequests(&LeaveRequest{})
}
# 程序输出
===========
要离职,人事审批!
处理离职!
请求完成!
===========
要加薪,项目经理审批!
处理加薪!
========
要请假,项目组长审批!
3、Java实现责任链模式1
package com.chainofresponsibility;// ========== 定义一个处理请求的接口Request ==========
public interface Request {void processing();
}
package com.chainofresponsibility;// ========== 请假LeaveRequest ==========
public class LeaveRequest implements Request{@Overridepublic void processing() {System.out.println("处理请假!");}
}
package com.chainofresponsibility;// ========== 加薪AddMoneyRequest ==========
public class AddMoneyRequest implements Request {@Overridepublic void processing() {System.out.println("处理加薪!");}
}
package com.chainofresponsibility;// ========== 离职DimissionRequest ==========
public class DimissionRequest implements Request{@Overridepublic void processing() {System.out.println("处理离职!");}
}
package com.chainofresponsibility;// 处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理请求,否则将该请求转发给它的后继者
// ========== RequestHandle ==========
public abstract class RequestHandle {RequestHandle requestHandle;abstract void handleRequest(Request request);void next(RequestHandle requestHandle){this.requestHandle = requestHandle;}
}
package com.chainofresponsibility;// ========== HRRequestHandle ==========
public class HRRequestHandle extends RequestHandle {@Overridepublic void handleRequest(Request request) {if (request instanceof DimissionRequest) {System.out.println("要离职,人事审批!");request.processing();}System.out.println("请求完成");}
}
package com.chainofresponsibility;// ========== PMRequestHandle ==========
public class PMRequestHandle extends RequestHandle {@Overridepublic void handleRequest(Request request) {if (request instanceof AddMoneyRequest) {System.out.println("要加薪,项目经理审批!");request.processing();} else {requestHandle.handleRequest(request);}}
}
package com.chainofresponsibility;public class TLRequestHandle extends RequestHandle {@Overridepublic void handleRequest(Request request) {if (request instanceof LeaveRequest) {System.out.println("要请假,项目组长审批!");request.processing();} else {requestHandle.handleRequest(request);}}
}
package com.chainofresponsibility;public class Test {public static void main(String[] args) {RequestHandle hr = new HRRequestHandle();RequestHandle pm = new PMRequestHandle();RequestHandle tl = new TLRequestHandle();tl.next(pm);pm.next(hr);System.out.println("===========");// 人事处理离职请求Request request = new DimissionRequest();tl.handleRequest(request);System.out.println("===========");// 项目经理处理加薪请求request = new AddMoneyRequest();tl.handleRequest(request);System.out.println("========");// 组长处理请假请求request = new LeaveRequest();tl.handleRequest(request);}
}
# 程序输出
===========
要离职,人事审批!
处理离职!
请求完成
===========
要加薪,项目经理审批!
处理加薪!
========
要请假,项目组长审批!
处理请假!
4、Go实现责任链模式2
创建 AbstractLogger,带有详细的日志记录级别,然后我们创建三种类型的记录器,都扩展了AbstractLogger。
每个记录器消息的级别是否属于自己的级别,如果是则相应打印出来,否则将消息传递给下一个记录器。
package chainofresponsibility// ========== Logger ==========
type Logger interface {LogMessage(level int, message string, logger Logger)Write(message string)
}
package chainofresponsibility// ========== AbstractLogger ==========
type AbstractLogger struct {Level intNextLogger Logger
}func (s *AbstractLogger) Write(message string) {
}func (s *AbstractLogger) LogMessage(level int, message string, logger Logger) {if s.Level <= level {logger.Write(message)} else {if s.NextLogger != nil {s.NextLogger.LogMessage(level, message, s.NextLogger)}}
}func (s *AbstractLogger) SetNextLogger(logger Logger) {s.NextLogger = logger
}
package chainofresponsibilityimport "fmt"// ========== FileLogger ==========
type FileLogger struct {AbstractLogger AbstractLogger
}func (f *FileLogger) Write(message string) {fmt.Println("File::Logger: " + message)
}func (f *FileLogger) LogMessage(level int, message string, logger Logger) {f.AbstractLogger.LogMessage(level, message, f)
}
package chainofresponsibilityimport "fmt"// ========== ConsoleLogger ==========
type ConsoleLogger struct {AbstractLogger
}func (c *ConsoleLogger) Write(message string) {fmt.Println("Standard Console::Logger: " + message)
}func (c *ConsoleLogger) LogMessage(level int, message string, logger Logger) {c.AbstractLogger.LogMessage(level, message, c)
}
package chainofresponsibilityimport "fmt"// ========== ErrorLogger ==========
type ErrorLogger struct {AbstractLogger AbstractLogger
}func (e *ErrorLogger) Write(message string) {fmt.Println("Error Console::Logger: " + message)
}func (e *ErrorLogger) LogMessage(level int, message string, logger Logger) {e.AbstractLogger.LogMessage(level, message, e)
}
package constantconst (DEBUG = iota + 1INFOERROR
)
package mainimport (. "proj/chainofresponsibility". "proj/constant"
)func main() {fileLogger := new(FileLogger)fileLogger.AbstractLogger.Level = DEBUGconsoleLogger := new(ConsoleLogger)consoleLogger.AbstractLogger.Level = INFOerrorLogger := new(ErrorLogger)errorLogger.AbstractLogger.Level = ERRORerrorLogger.AbstractLogger.SetNextLogger(consoleLogger)consoleLogger.AbstractLogger.SetNextLogger(fileLogger)errorLogger.LogMessage(DEBUG, "This is a debug level information.", nil)errorLogger.LogMessage(INFO, "This is an info level information.", nil)errorLogger.LogMessage(ERROR, "This is an error level information.", nil)}
# 程序输出
File::Logger: This is a debug level information.
Standard Console::Logger: This is an info level information.
Error Console::Logger: This is an error level information.
5、Java实现责任链模式2
package com.chainofresponsibility;// ========== AbstractLogger ==========
public abstract class AbstractLogger {protected int level;// 责任链中的下一个元素protected AbstractLogger nextLogger;public void setLevel(int level) {this.level = level;}public void setNextLogger(AbstractLogger nextLogger) {this.nextLogger = nextLogger;}public void logMessage(int level, String message) {if (this.level <= level) {write(message);}else{if(nextLogger != null) {nextLogger.logMessage(level, message);}}}abstract protected void write(String message);
}
package com.chainofresponsibility;// ========== FileLogger ==========
public class FileLogger extends AbstractLogger {@Overrideprotected void write(String message) {System.out.println("File::Logger: " + message);}
}
package com.chainofresponsibility;// ========== ConsoleLogger ==========
public class ConsoleLogger extends AbstractLogger {@Overrideprotected void write(String message) {System.out.println("Standard Console::Logger: " + message);}
}
package com.chainofresponsibility;// ========== ErrorLogger ==========
public class ErrorLogger extends AbstractLogger {@Overrideprotected void write(String message) {System.out.println("Error Console::Logger: " + message);}
}
package com.chainofresponsibility;public class Constant {public static int DEBUG = 1;public static int INFO = 2;public static int ERROR = 3;
}
package com.chainofresponsibility;public class Test {public static void main(String[] args) {AbstractLogger fileLogger = new FileLogger();fileLogger.setLevel(Constant.DEBUG);AbstractLogger consoleLogger = new ConsoleLogger();consoleLogger.setLevel(Constant.INFO);AbstractLogger errorLogger = new ErrorLogger();errorLogger.setLevel(Constant.ERROR);errorLogger.setNextLogger(consoleLogger);consoleLogger.setNextLogger(fileLogger);errorLogger.logMessage(Constant.DEBUG, "This is a debug level information.");errorLogger.logMessage(Constant.INFO, "This is an info level information.");errorLogger.logMessage(Constant.ERROR, "This is an error level information.");}
}
# 程序输出
File::Logger: This is a debug level information.
Standard Console::Logger: This is an info level information.
Error Console::Logger: This is an error level information.
相关文章:
Go和Java实现责任链模式
Go和Java实现责任链模式 下面通过一个审批流程的案例来说明责任链模式的使用。 1、责任链模式 责任链模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这 种类型的设计模式属于行为型模式。 在这种模式中&#x…...
C#+GDAL影像处理笔记08:生成DEM的图阔范围线
目录 1 实现思路 2 源码及解析 1 实现思路 首先获取DEM数据的转换参数信息,这个信息记录了DEM的放射变换参数,包括左上角X,X方向分辨率、0、左上角Y、0、Y方向的分辨率【负值】等信息。接着是根据转换参数,计算DEM分幅数据的四至范围坐标;主要用到上一步得到的转换参数信…...

敏捷研发管理软件及敏捷管理流程
Scrum中非常强调公开、透明、直接有效的沟通,这也是“可视化的管理工具”在敏捷开发中如此重要的原因之一。通过“可视化的管理工具”让所有人直观的看到需求,故事,任务之间的流转状态,可以使团队成员更加快速适应敏捷开发流程。 …...

Mac OS 13.4.1 搜狗输入法导致的卡顿问题
一、Mac OS 系统版本 搜狗输入法已经更新到最新 二、解决方案 解决方案一 在我的电脑上面需要关闭 VSCode 和 Chrmoe 以后,搜狗输入法回复正常。 解决方案二 强制重启一下搜狗输入法。 可以用 unix 定时任务去隔 2个小时自动 kill 掉一次进程 # kill 掉 mac …...

vue 简单实验 自定义组件 局部注册
1.概要 2.代码 <html> </html> <script src"https://unpkg.com/vuenext" rel"external nofollow" ></script> <body><div id"counter"><component-a></component-a></div> </body&g…...

Resnet模型详解
1、Resnet是什么? Resnet是一种深度神经网络架构,被广泛用于计算机视觉任务,特别是图像分类。它是由微软研究院的研究员于2015年提出的,是深度学习领域的重要里程碑之一。 2、网络退化问题 理论上来讲,随着网络的层…...

AI 绘画Stable Diffusion 研究(十六)SD Hypernetwork详解
大家好,我是风雨无阻。 本期内容: 什么是 Hypernetwork?Hypernetwork 与其他模型的区别?Hypernetwork 原理Hypernetwork 如何下载安装?Hypernetwork 如何使用? 在上一篇文章中,我们详细介绍了 …...

2023.8 -java - 继承
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。 继承的特性 子类拥有父类非 private 的属性、方法。 子类可以拥有自己的属性和方法…...
前端面试:【移动端开发】PWA、Hybrid App和Native App的比较
在移动端开发中,开发者有多种选择,包括渐进式Web应用(PWA),混合应用(Hybrid App)和原生应用(Native App)。每种方法都有其独特的优势和适用场景。本文将对它们进行比较&a…...

picGo+gitee+typora设置图床
picGogiteetypora设置图床 picGogitee设置图床下载picGo软件安装picGo软件gitee操作在gitee中创建仓库在gitee中配置私人令牌 配置picGo在插件设置中搜索gitee插件并进行下载 TyporapicGo设置Typora 下载Typora进行图像设置 picGogitee设置图床 当我了解picGogitee可以设置图床…...

[JavaWeb]【十三】web后端开发-原理篇
目录 一、SpringBoot配置优先级 1.1 配置优先级比较 1.2 java系统属性和命令行参数 1.3 打包运行jar 1.4 综合优先级编辑 二、Bean管理 2.1 获取bean 2.2 bean作用域 2.2.1 五种作用域 2.2.2 配置作用域 2.3 第三方bean 2.3.1 编写公共配置类 三、SpringBoot原理 …...

服务注册中心 Eureka
服务注册中心 Eureka Spring Cloud Eureka 是 Netflix 公司开发的注册发现组件,本身是一个基于 REST 的服务。提供注册与发现,同时还提供了负载均衡、故障转移等能力。 Eureka 有 3 个角色 服务中心(Eureka Server):…...

SpringIoC组件的高级特性
目录 一、Bean组件的周期与作用域 二、FactoryBean接口 一、Bean组件的周期与作用域 1.1 Bean组件的生命周期 什么是Bean的周期方法 我们可以在组件类中定义方法,然后当IoC容器实例化和销毁组件对象的时候进行调用!这两个方法我们成为生命周期方法&a…...

Linux--进程地址空间
1.线程地址空间 所谓进程地址空间(process address space),就是从进程的视角看到的地址空间,是进程运行时所用到的虚拟地址的集合。 简单地说,进程就是内核数据结构和代码和本身的代码和数据,进程本身不能…...

ISIS路由协议
骨干区域与非骨干区域 凡是由级别2组建起来的邻居形成骨干区域;级别1就在非骨干区域,骨干区域有且只有一个,并且需要连续,ISIS在IP环境下目前不支持虚链路。 路由器级别 L1路由器只能建立L1的邻居;L2路由器只能建立L…...
论文解读:Bert原理深入浅出
摘取于https://www.jianshu.com/p/810ca25c4502 任务1:Masked Language Model Maked LM 是为了解决单向信息问题,现有的语言模型的问题在于,没有同时利用双向信息,如 ELMO 号称是双向LM,但实际上是两个单向 RNN 构成的…...

共享内存 windows和linux
服务端,即写入端 #include <iostream> #include <string.h> #define BUF_SIZE 1024 #ifdef _WIN32 #include <windows.h> #define SHARENAME L"shareMemory" HANDLE g_MapFIle; LPVOID g_baseBuffer; #else #define SHARENAME "sh…...
一个mongodb问题分析
mongodb问题分析 现状 表的个数: 生产上常用的表就10来个。 sharding cluster replica set方式部署: 9个shard server, 每个shard server 1主2从, 大量数据写入时或对大表创建索引时,可能有主从复制延迟问题。实…...

Vue3.0极速入门- 目录和文件说明
目录结构 以下文件均为npm create helloworld自动生成的文件目录结构 目录截图 目录说明 目录/文件说明node_modulesnpm 加载的项目依赖模块src这里是我们要开发的目录,基本上要做的事情都在这个目录里assets放置一些图片,如logo等。componentsvue组件…...

RabbitMQ---订阅模型-Direct
1、 订阅模型-Direct • 有选择性的接收消息 • 在订阅模式中,生产者发布消息,所有消费者都可以获取所有消息。 • 在路由模式中,我们将添加一个功能 - 我们将只能订阅一部分消息。 例如,我们只能将重要的错误消息引导到日志文件…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析
MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录,这个目录下存放着许多可执行文件。与其他系统的可执行文件类似,这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中,用…...

鸿蒙Navigation路由导航-基本使用介绍
1. Navigation介绍 Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(Navigation的子组件)或非首页显示(Nav…...
python读取SQLite表个并生成pdf文件
代码用于创建含50列的SQLite数据库并插入500行随机浮点数据,随后读取数据,通过ReportLab生成横向PDF表格,包含格式化(两位小数)及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...

20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题
20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题 2025/6/9 20:54 缘起,为了跨网段推流,千辛万苦配置好了网络参数。 但是命令iptables -t filter -F tetherctrl_FORWARD可以在调试串口/DEBUG口正确执行。…...