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 • 有选择性的接收消息 • 在订阅模式中,生产者发布消息,所有消费者都可以获取所有消息。 • 在路由模式中,我们将添加一个功能 - 我们将只能订阅一部分消息。 例如,我们只能将重要的错误消息引导到日志文件…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
