设计模式:责任链模式(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产品研发经验、团队管理经验,同济本复旦硕࿰…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
