设计模式:责任链模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)
上一篇《享元模式》 下一篇《解释器模式》
简介:
责任链模式,它是一种行为型设计模式,它将许多对象连接起来形成一条链,每个对象处理不同的请求,当一个请求从链的首端发出时,会沿着链路的路径依次传递给每一个对象,直到有对象处理该请求为止。
在责任链模式中,每个处理对象都包含对下一个处理对象的引用,请求会沿着这个链一路传递下去,直到找到一个能够处理该请求的处理对象。在这种模式下,请求的发送者并不知道哪个对象会处理该请求,因此系统可以在不影响客户端的情况下动态地重新组织和分配责任。
责任链模式的使用场景:
1、多个对象可以处理同一个请求,但具体由哪个对象处理则在运行时动态决定。
2、在请求处理者不明确的情况下,向多个对象中的一个提交一个请求。
3、需要动态处理一组对象处理请求。
责任链模式的创建步骤:
1、定义一个抽象的处理器(Handler)接口,其中包含处理请求的方法以及设置下一个处理器的引用。例如:type Handler interface { SetNext(handler Handler) Handle(request interface{}) }。
2、创建具体的处理器类型,并且实现Handler接口。在处理请求时,如果当前处理器无法处理该请求,则将请求转发给下一个处理器。
3、将具体处理器初始化到链条中,并做抽象方法的具体实现。
4、设计链条结束标识,例如通过pos游标。
在实现责任链模式时,需要注意以下几点:
1、每个处理器都需要能够找到下一个处理器,因此需要在Handler接口中设置下一个处理器的引用。
2、每个处理器都需要能够处理其能够处理的请求,如果当前处理器无法处理该请求,则需要将请求转发给下一个处理器。
3、在设计链条时,需要注意如何将处理器正确地连接起来,以避免出现无限循环的情况。
4、在设计链条时,还需要考虑如何处理多个处理器同时能够处理同一请求的情况。
责任链模式的优点,主要包括:
1、降低对象之间的耦合度:责任链模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
2、增强系统的可扩展性:可以根据需要增加新的请求处理类,满足开闭原则。
3、增强给对象指派职责的灵活性:当工作流程发生变化时,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
4、简化对象之间的连接:每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的if或者if···else语句。
5、责任分担:每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
责任链模式的缺点,主要包括:
1、性能问题:每个请求都需要从链表头遍历到链表尾,特别是在链表比较长的情况下,性能会受到很大影响。
2、调试不方便:特别是当链表比较长,环节比较多的时候,由于采用了类似递归的方式,调试时可能逻辑比较复杂。

示例:
一、C#责任链模式
以下是一个示例,展示了如何在C#中实现责任链模式:
using System; //定义一个处理者接口
public interface IHandler
{ void HandleRequest();
} //定义具体的处理者类1
public class Handler1 : IHandler
{ public void HandleRequest() { Console.WriteLine("Handler1处理请求"); }
} //定义具体的处理者类2
public class Handler2 : IHandler
{ public void HandleRequest() { Console.WriteLine("Handler2处理请求"); }
} //定义请求类
public class Request
{ private string requestType;public Request(string requestType){ this.requestType = requestType;} public string GetRequestType(){return this.requestType;}
}
//定义请求处理器(RequestProcessor)类,它持有一个处理者(Handler)的引用,并调用它的handleRequest方法。如果当前处理者不能处理该请求,它将请求传递给链中的下一个处理者。
public class RequestProcessor { private IHandler handler; public RequestProcessor(IHandler handler) { this.handler = handler; } public void ProcessRequest(Request request) { handler.handleRequest(); }
}
//使用示例:
class Program
{ static void Main(string[] args) { IHandler handler1 = new Handler1(); IHandler handler2 = new Handler2(); Request request1 = new Request("Request1"); Request request2 = new Request("Request2"); RequestProcessor processor1 = new RequestProcessor(handler1); processor1.ProcessRequest(request1); // 输出 "Handler1 handled the request." processor1.ProcessRequest(request2); // 输出 "Handler2 handled the request." }
}
二、java责任链模式
责任链模式通常通过以下方式实现:
// 定义一个处理者(Handler)接口
public interface Handler { void handleRequest();
} // 定义具体处理者类1(ConcreteHandler1)
public class ConcreteHandler1 implements Handler { @Override public void handleRequest() { System.out.println("ConcreteHandler1 handled the request."); }
} // 定义具体处理者类2(ConcreteHandler2)
public class ConcreteHandler2 implements Handler { @Override public void handleRequest() { System.out.println("ConcreteHandler2 handled the request."); }
} // 定义请求类(Request)
public class Request { private String requestType; public Request(String requestType) { this.requestType = requestType; } public String getRequestType() { return requestType; }
} // 定义请求处理器(RequestProcessor)类,它持有一个处理者(Handler)的引用,并调用它的handleRequest方法。如果当前处理者不能处理该请求,它将请求传递给链中的下一个处理者。
public class RequestProcessor { private Handler handler; public RequestProcessor(Handler handler) { this.handler = handler; } public void processRequest(Request request) { handler.handleRequest(); }
} // 测试类(Test)用于模拟客户端代码。它创建了几个处理者和请求对象,并使用请求处理器来处理请求。
public class Test { public static void main(String[] args) { // 创建几个处理者对象和请求对象。注意,ConcreteHandler2 的 handleRequest 方法会在请求类型为 "Request2" 时被调用。 Handler handler1 = new ConcreteHandler1(); Handler handler2 = new ConcreteHandler2(); Request request1 = new Request("Request1"); Request request2 = new Request("Request2"); Request request3 = new Request("Request3"); // 使用请求处理器来处理请求。注意,每个请求处理器都可以持有一个处理者对象,并在需要时将请求传递给这个处理者对象。这种设计方式使得你可以轻松地改变请求的处理流程。 RequestProcessor processor1 = new RequestProcessor(handler1); processor1.processRequest(request1); // 输出 "ConcreteHandler1 handled the request." processor1.processRequest(request2); // 输出 "ConcreteHandler2 handled the request." 因为ConcreteHandler2 可以处理Request2 类型的请求. 这里因为处理器链条的设置,没有找到合适的处理器,所以会输出 "No handler can handle the request." 而不会继续传递给下一个处理器。因此,在这种情况下,处理器链条的最后一个处理器决定了处理结果。同理,对于类型为 "Request3" 的请求也没有找到合适的处理器来处理,因此输出 "No handler can handle the request."。
三、javascript责任链模式
在JavaScript中,责任链实现方式如下:
class Handler { constructor() { this.next = null; } handleRequest(request) { if (this.canHandle(request)) { console.log(`${this.name} handled request ${request}`); return true; } else if (this.next) { return this.next.handleRequest(request); } else { console.log('No handler found for request'); return false; } } canHandle(request) { return false; }
} class HandlerA extends Handler { constructor() { super(); this.name = 'HandlerA'; } canHandle(request) { return request.type === 'A'; }
} class HandlerB extends Handler { constructor() { super(); this.name = 'HandlerB'; } canHandle(request) { return request.type === 'B'; }
} class HandlerC extends Handler { constructor() { super(); this.name = 'HandlerC'; } canHandle(request) { return request.type === 'C'; }
}
//使用示例:
const handlerA = new HandlerA();
const handlerB = new HandlerB();
const handlerC = new HandlerC();
handlerA.next = handlerB; handlerB.next = handlerC;
handlerA.handleRequest({ type: 'A' }); // Output: HandlerA handled request A
handlerA.handleRequest({ type: 'B' }); // Output: HandlerA handled request B
handlerA.handleRequest({ type: 'C' }); // Output: HandlerA handled request C
handlerA.handleRequest({ type: 'D' }); // Output: No handler found for request
四、C++责任链模式
以下是在C++中实现责任链模式:
#include <iostream>
using namespace std; // 定义责任链中的节点类
class Handler {
public: virtual bool canHandle(int request) = 0; virtual void handleRequest(int request) = 0;
}; // 定义具体的处理器类
class HandlerA : public Handler {
public: bool canHandle(int request) { return request >= 1 && request <= 5; } void handleRequest(int request) { cout << "HandlerA handles request: " << request << endl; }
}; class HandlerB : public Handler {
public: bool canHandle(int request) { return request > 5 && request <= 10; } void handleRequest(int request) { cout << "HandlerB handles request: " << request << endl; }
}; class HandlerC : public Handler {
public: bool canHandle(int request) { return request > 10 && request <= 15; } void handleRequest(int request) { cout << "HandlerC handles request: " << request << endl; }
}; // 定义责任链类,负责将请求传递给合适的处理器节点进行处理
class ResponsibilityChain {
private: Handler* head;
public: ResponsibilityChain(Handler* handler) { head = handler; } void processRequest(int request) { Handler* currentHandler = head; while (currentHandler != nullptr) { if (currentHandler->canHandle(request)) { currentHandler->handleRequest(request); break; } else { currentHandler = currentHandler->next; } } }
}; int main() { // 创建责任链对象,并将处理器节点按顺序链接起来形成责任链 ResponsibilityChain chain(new HandlerA()); chain.processRequest(3); // HandlerA handles request: 3 输出:3的处理由HandlerA完成。
五、python责任链模式
以下是在python中实现责任链模式:
class Handler: def __init__(self): self.next = None def handle_request(self, request): if self.can_handle(request): print(f"{self.__class__.__name__} handles request: {request}") return True elif self.next: return self.next.handle_request(request) else: print("No handler found for request") return False def can_handle(self, request): return False class ConcreteHandlerA(Handler): def can_handle(self, request): return request <= 5 class ConcreteHandlerB(Handler): def can_handle(self, request): return request > 5 and request <= 10 class ConcreteHandlerC(Handler): def can_handle(self, request): return request > 10 and request <= 15 def main(): handlerA = ConcreteHandlerA() handlerB = ConcreteHandlerB() handlerC = ConcreteHandlerC() handlerA.next = handlerB handlerB.next = handlerC handlerA.handle_request(3) # Output: ConcreteHandlerA handles request: 3 handlerA.handle_request(6) # Output: ConcreteHandlerB handles request: 6 handlerA.handle_request(12) # Output: ConcreteHandlerC handles request: 12 handlerA.handle_request(18) # Output: No handler found for request if __name__ == "__main__": main()
六、go责任链模式
以下是一个示例,展示了如何在go中实现责任链模式:
package main import "fmt" type Handler interface { HandleRequest() bool
} type ConcreteHandlerA struct{} func (h ConcreteHandlerA) HandleRequest() bool { fmt.Println("ConcreteHandlerA handles request") return true
} type ConcreteHandlerB struct{} func (h ConcreteHandlerB) HandleRequest() bool { fmt.Println("ConcreteHandlerB handles request") return true
} type ConcreteHandlerC struct{} func (h ConcreteHandlerC) HandleRequest() bool { fmt.Println("ConcreteHandlerC handles request") return true
} func main() { handlerA := ConcreteHandlerA{} handlerB := ConcreteHandlerB{} handlerC := ConcreteHandlerC{} handlerA.HandleRequest() // Output: ConcreteHandlerA handles request handlerB.HandleRequest() // Output: ConcreteHandlerB handles request handlerC.HandleRequest() // Output: ConcreteHandlerC handles request
}
七、PHP责任链模式
以下是一个示例,展示了如何在PHP中实现责任链模式:
<?php interface HandlerInterface { public function handleRequest($request);
} class ConcreteHandlerA implements HandlerInterface { private $nextHandler; public function __construct(HandlerInterface $nextHandler) { $this->nextHandler = $nextHandler; } public function handleRequest($request) { if ($request <= 5) { echo "ConcreteHandlerA handles request: $request\n"; return true; } elseif ($this->nextHandler) { return $this->nextHandler->handleRequest($request); } else { echo "No handler found for request\n"; return false; } }
} class ConcreteHandlerB implements HandlerInterface { private $nextHandler; public function __construct(HandlerInterface $nextHandler) { $this->nextHandler = $nextHandler; } public function handleRequest($request) { if ($request > 5 && $request <= 10) { echo "ConcreteHandlerB handles request: $request\n"; return true; } elseif ($this->nextHandler) { return $this->nextHandler->handleRequest($request); } else { echo "No handler found for request\n"; return false; } }
} class ConcreteHandlerC implements HandlerInterface { private $nextHandler; public function __construct(HandlerInterface $nextHandler) { $this->nextHandler = $nextHandler; } public function handleRequest($request) { if ($request > 10 && $request <= 15) { echo "ConcreteHandlerC handles request: $request\n"; return true; } elseif ($this->nextHandler) { return $this->nextHandler->handleRequest($request); } else { echo "No handler found for request\n"; return false; } }
} $handlerA = new ConcreteHandlerA(new ConcreteHandlerB(new ConcreteHandlerC()));
$handlerA->handleRequest(3); // Output: ConcreteHandlerA handles request: 3
$handlerA->handleRequest(6); // Output: ConcreteHandlerB handles request: 6
$handlerA->handleRequest(12); // Output: ConcreteHandlerC handles request: 12
$handlerA->handleRequest(18); // Output: No handler found for request ?>
《完结》
上一篇《享元模式》 下一篇《解释器模式》
相关文章:
设计模式:责任链模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)
上一篇《享元模式》 下一篇《解释器模式》 简介: 责任链模式,它是一种行为型设计模式,它将许多对象连接起来形成一条链,每个对象处理不同的请求,…...
koa搭建服务器(二)
在上一篇文章已经成功的运行了一个http服务器,接下来就是使用Sequelize ORM(官方文档:Sequelize 简介 | Sequelize中文文档 | Sequelize中文网)来操作数据库。 1、安装依赖 首先也是需要安装相关的依赖 npm i sequelize npm i …...
LeetCode 125 验证回文串 简单
题目 - 点击直达 1. 125 验证回文串 简单1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 1. 125 验证回文串 简单 1. 题目详情 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反…...
Android底层摸索改BUG(一):Android系统状态栏显示不下Wifi图标
这是我入职的第一个BUG,头疼,隔壁实习生一周解决了,我多花了几天 其中最大的原因就是我思考复杂了,在公司系统上,此BUG标题为: 请确认Wifi优先级,状态栏Wifi被忽略 BUG意思就是:当…...
第十三章---枚举类型与泛型
一,枚举类型 1.使用枚举类型设置常量 设置常量时,我们通常将常量放置在接口中,这样在程序中就可以直接使用。该常量稚因为在接口中定义常量时,该常量的修饰符为 final 与 static。 public interface Constants ( public static …...
shell语法大全(超级详细!!!!),非常适合入门
本文旨在对y总的Linux基础课shell语法做学习记录,指令较多,方便日后查找。 参考视频:Linux基础课 参考教程:Linux教程 1 概论 Linux中常见的shell脚本有很多种,常见的有: Bourne Shell(/usr/bin/sh或/bi…...
【Python机器学习】零基础掌握ExtraTreesRegressor集成学习
面临的问题:如何更准确地预测糖尿病患者的病情? 在医疗领域,准确预测疾病的发展状况是至关重要的。尤其是对于糖尿病这样的慢性病,一个精准的预测模型能帮助医生制定更有效的治疗方案。但问题是,如何构建一个高准确度的预测模型呢? 假设现有一组糖尿病患者的医疗数据,…...
网络协议--TCP的交互数据流
19.1 引言 前一章我们介绍了TCP连接的建立与释放,现在来介绍使用TCP进行数据传输的有关问题。 一些有关TCP通信量的研究如[Caceres et al. 1991]发现,如果按照分组数量计算,约有一半的TCP报文段包含成块数据(如FTP、电子邮件和U…...
IOC课程整理-13 Spring校验
1. Spring 校验使用场景 2. Validator 接口设计 3. Errors 接口设计 4. Errors 文案来源 5. 自定义 Validator 6. Validator 的救赎 7. 面试题精选 Spring 校验接口是哪个 org.springframework.validation.Validator Spring 有哪些校验核心组件?...
SSM咖啡点餐管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目
一、源码特点 SSM 咖啡点餐管理系统是一套完善的信息系统,结合SSM框架完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库,系统主 要采用B/S模式开…...
Capacitor 打包 h5 到 Android 应用,uniapp https http net::ERR_CLEARTEXT_NOT_PERMITTED
Capacitor 打包 h5 到 Android 应用,uniapp https http net::ERR_CLEARTEXT_NOT_PERMITTED capacitor 官网: https://capacitorjs.com/docs/ 项目上需要做一个 app,而这个 app 是用 uniapp 做的,里面用到了一个依赖 dom 的库&…...
华为数通方向HCIP-DataCom H12-831题库(多选题:101-120)
第101题 LSR对收到的标签进行保留,且保留方式有多种,那么以下关于LDP标签保留一自由方式的说法 A、保留邻居发送来的所有标签 B、需要更多的内存和标签空间 C、只保留来自下一跳邻居的标签,丢弃所有非下一跳铃邻居发来的标签 D、节省内存和标签空间 E、当IP路由收敛、下一跳…...
misc学习(4)Traffic(流量分析)-
感悟:回想起自己学的计算机网络和网络协议分析,有所感悟:计算机网络好比将一群人区分开来(局域网),为了能够使得不同部分的人能够沟通(wireshark中的数据包),就设置了网络…...
Less的基本语法
less的每一个语句后必须使用";"结束,否则可能无法正确的转换成css 1、导入 即在当前less文件中引用其它less文件,被引入的less文件中的内容可以在此less文件中使用。在引用less文件时可以省略扩展名 import "global"; // global.…...
spring boot项目优雅停机
1、关闭流程 停止接收请求和内部线程。判断是否有线程正在执行。等待正在执行的线程执行完毕。停止容器。 2、关闭过程有新的请求 在kill Spring Boot项目时,如果有访问请求过来,请求会被拒绝并返回错误提示。 在kill Spring Boot项目时,Sp…...
链式存储方式下字符串的replace(S,T1,T2)运算
链式存储方式下字符串的replace运算 ⭐️题目⭐️思路⭐️代码✨定义结点✨打印字符串函数✨计算字符串函数✨初始化字符串函数✨代码解读✨字符串替换函数✨字符串替换函数解读✨ 主函数✨完整代码 实现在链式存储下字符串的replace(S,T1,T2),来自课本习题的一道题…...
unity脚本_Mathf和Math c#
首先创建一个脚本 当我们要做一个值趋近于一个值变化时 可以用Mathf.Lerp(start,end,time);方法实现 比如物体跟随...
轻量级仿 Spring Boot=嵌入式 Tomcat+Spring MVC
啥?Spring Boot 不用?——对。就只是使用 Spring MVC Embedded Tomcat,而不用 Boot。为啥?——因为 Boot 太重了:) 那是反智吗?Spring Boot 好好的就只是因为太重就不用?——稍安勿…...
笔记Kubernetes核心技术-之Controller
2、Controller 2.1、概述 在集群上管理和运行容器的对象,控制器(也称为:工作负载),Controller实际存在的,Pod是抽象的; 2.2、Pod和Controller关系 Pod是通过Controller实现应用运维,比如:弹…...
Azure云工作站上做Machine Learning模型开发 - 全流程演示
目录 本文内容先决条件从“笔记本”开始设置用于原型制作的新环境(可选)创建笔记本开发训练脚本迭代检查结果 关注TechLead,分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕࿰…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
Yii2项目自动向GitLab上报Bug
Yii2 项目自动上报Bug 原理 yii2在程序报错时, 会执行指定action, 通过重写ErrorAction, 实现Bug自动提交至GitLab的issue 步骤 配置SiteController中的actions方法 public function actions(){return [error > [class > app\helpers\web\ErrorAction,],];}重写Error…...
【Redis】Redis从入门到实战:全面指南
Redis从入门到实战:全面指南 一、Redis简介 Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,它可以用作数据库、缓存和消息代理。由Salvatore Sanfilippo于2009年开发,因其高性能、丰富的数据结构和广泛的语言支持而广受欢迎。 Redis核心特点:…...
Docker环境下安装 Elasticsearch + IK 分词器 + Pinyin插件 + Kibana(适配7.10.1)
做RAG自己打算使用esmilvus自己开发一个,安装时好像网上没有比较新的安装方法,然后找了个旧的方法对应试试: 🚀 本文将手把手教你在 Docker 环境中部署 Elasticsearch 7.10.1 IK分词器 拼音插件 Kibana,适配中文搜索…...
联邦学习带宽资源分配
带宽资源分配是指在网络中如何合理分配有限的带宽资源,以满足各个通信任务和用户的需求,尤其是在多用户共享带宽的情况下,如何确保各个设备或用户的通信需求得到高效且公平的满足。带宽是网络中的一个重要资源,通常指的是单位时间…...
