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

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...