当前位置: 首页 > article >正文

设计模式之责任链模式:原理、实现与应用

引言

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象有机会处理请求,从而避免请求的发送者与接收者之间的耦合。责任链模式通过将多个处理对象连接成一条链,使得请求沿着链传递,直到有对象处理它为止。本文将深入探讨责任链模式的原理、实现方式以及实际应用场景,帮助你更好地理解和使用这一设计模式。


1. 责任链模式的核心概念

1.1 什么是责任链模式?

责任链模式是一种行为型设计模式,它允许多个对象有机会处理请求,从而避免请求的发送者与接收者之间的耦合。责任链模式通过将多个处理对象连接成一条链,使得请求沿着链传递,直到有对象处理它为止。

1.2 责任链模式的应用场景
  • 多级审批:如请假审批、报销审批等。

  • 事件处理:如GUI事件处理、异常处理等。

  • 过滤器链:如Web请求过滤器、日志过滤器等。


2. 责任链模式的实现方式

2.1 基本结构

责任链模式通常包含以下几个角色:

  • 处理者接口(Handler):定义处理请求的接口,并持有下一个处理者的引用。

  • 具体处理者(Concrete Handler):实现处理者接口,处理请求或将请求传递给下一个处理者。

  • 客户端(Client):创建责任链,并向链中的第一个处理者发送请求。

2.2 代码示例
// 处理者接口
public interface Handler {void setNext(Handler next);void handleRequest(Request request);
}// 具体处理者A
public class ConcreteHandlerA implements Handler {private Handler next;@Overridepublic void setNext(Handler next) {this.next = next;}@Overridepublic void handleRequest(Request request) {if (request.getType().equals("TypeA")) {System.out.println("ConcreteHandlerA handled the request");} else if (next != null) {next.handleRequest(request);}}
}// 具体处理者B
public class ConcreteHandlerB implements Handler {private Handler next;@Overridepublic void setNext(Handler next) {this.next = next;}@Overridepublic void handleRequest(Request request) {if (request.getType().equals("TypeB")) {System.out.println("ConcreteHandlerB handled the request");} else if (next != null) {next.handleRequest(request);}}
}// 请求类
public class Request {private String type;public Request(String type) {this.type = type;}public String getType() {return type;}
}// 客户端代码
public class Client {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNext(handlerB);Request request1 = new Request("TypeA");handlerA.handleRequest(request1);Request request2 = new Request("TypeB");handlerA.handleRequest(request2);Request request3 = new Request("TypeC");handlerA.handleRequest(request3);}
}

3. 责任链模式的最佳实践

3.1 动态构建责任链
  • 灵活性:通过动态构建责任链,可以根据需要调整处理者的顺序和数量。

  • 可扩展性:通过添加新的处理者,可以轻松扩展责任链的功能。

3.2 避免循环引用
  • 循环引用:在构建责任链时,避免处理者之间形成循环引用,导致请求无限循环。

3.3 遵循单一职责原则
  • 单一职责:每个处理者只负责处理特定类型的请求,保持职责单一。

  • 高内聚低耦合:责任链模式使得系统更加高内聚低耦合。


4. 责任链模式的实际应用

4.1 多级审批

在多级审批中,责任链模式用于处理不同级别的审批请求。

// 处理者接口
public interface Approver {void setNext(Approver next);void approve(int amount);
}// 具体处理者
public class Manager implements Approver {private Approver next;@Overridepublic void setNext(Approver next) {this.next = next;}@Overridepublic void approve(int amount) {if (amount <= 1000) {System.out.println("Manager approved the request");} else if (next != null) {next.approve(amount);}}
}public class Director implements Approver {private Approver next;@Overridepublic void setNext(Approver next) {this.next = next;}@Overridepublic void approve(int amount) {if (amount <= 5000) {System.out.println("Director approved the request");} else if (next != null) {next.approve(amount);}}
}public class CEO implements Approver {@Overridepublic void setNext(Approver next) {// CEO is the final approver}@Overridepublic void approve(int amount) {System.out.println("CEO approved the request");}
}// 客户端代码
public class Client {public static void main(String[] args) {Approver manager = new Manager();Approver director = new Director();Approver ceo = new CEO();manager.setNext(director);director.setNext(ceo);manager.approve(500);manager.approve(2000);manager.approve(10000);}
}
4.2 事件处理

在事件处理中,责任链模式用于处理不同类型的事件。

// 处理者接口
public interface EventHandler {void setNext(EventHandler next);void handle(Event event);
}// 具体处理者
public class MouseEventHandler implements EventHandler {private EventHandler next;@Overridepublic void setNext(EventHandler next) {this.next = next;}@Overridepublic void handle(Event event) {if (event.getType().equals("MouseEvent")) {System.out.println("MouseEventHandler handled the event");} else if (next != null) {next.handle(event);}}
}public class KeyboardEventHandler implements EventHandler {private EventHandler next;@Overridepublic void setNext(EventHandler next) {this.next = next;}@Overridepublic void handle(Event event) {if (event.getType().equals("KeyboardEvent")) {System.out.println("KeyboardEventHandler handled the event");} else if (next != null) {next.handle(event);}}
}// 事件类
public class Event {private String type;public Event(String type) {this.type = type;}public String getType() {return type;}
}// 客户端代码
public class Client {public static void main(String[] args) {EventHandler mouseHandler = new MouseEventHandler();EventHandler keyboardHandler = new KeyboardEventHandler();mouseHandler.setNext(keyboardHandler);Event mouseEvent = new Event("MouseEvent");mouseHandler.handle(mouseEvent);Event keyboardEvent = new Event("KeyboardEvent");mouseHandler.handle(keyboardEvent);Event unknownEvent = new Event("UnknownEvent");mouseHandler.handle(unknownEvent);}
}
4.3 过滤器链

在过滤器链中,责任链模式用于处理Web请求或日志记录。

// 处理者接口
public interface Filter {void setNext(Filter next);void doFilter(Request request);
}// 具体处理者
public class AuthenticationFilter implements Filter {private Filter next;@Overridepublic void setNext(Filter next) {this.next = next;}@Overridepublic void doFilter(Request request) {if (request.getType().equals("Authentication")) {System.out.println("AuthenticationFilter handled the request");} else if (next != null) {next.doFilter(request);}}
}public class LoggingFilter implements Filter {private Filter next;@Overridepublic void setNext(Filter next) {this.next = next;}@Overridepublic void doFilter(Request request) {if (request.getType().equals("Logging")) {System.out.println("LoggingFilter handled the request");} else if (next != null) {next.doFilter(request);}}
}// 请求类
public class Request {private String type;public Request(String type) {this.type = type;}public String getType() {return type;}
}// 客户端代码
public class Client {public static void main(String[] args) {Filter authenticationFilter = new AuthenticationFilter();Filter loggingFilter = new LoggingFilter();authenticationFilter.setNext(loggingFilter);Request authRequest = new Request("Authentication");authenticationFilter.doFilter(authRequest);Request logRequest = new Request("Logging");authenticationFilter.doFilter(logRequest);Request unknownRequest = new Request("Unknown");authenticationFilter.doFilter(unknownRequest);}
}

5. 责任链模式的优缺点

5.1 优点
  • 解耦:责任链模式将请求的发送者与接收者解耦,使得请求的发送者无需知道具体的处理者。

  • 灵活性:通过动态构建责任链,可以根据需要调整处理者的顺序和数量。

  • 可扩展性:通过添加新的处理者,可以轻松扩展责任链的功能。

5.2 缺点
  • 性能问题:如果责任链过长,可能会导致性能问题。

  • 请求未被处理:如果请求未被任何处理者处理,可能会导致请求丢失。


结语

责任链模式是设计模式中用于处理请求的经典模式之一,适用于需要将请求的发送者与接收者解耦的场景。通过掌握责任链模式的原理、实现方式以及最佳实践,你可以在实际开发中更好地应用这一模式。希望本文能为你的设计模式学习之旅提供一些实用的指导!


如果你有具体的需求或想要深入探讨某个主题,请告诉我,我可以进一步调整内容!

相关文章:

设计模式之责任链模式:原理、实现与应用

引言 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许多个对象有机会处理请求&#xff0c;从而避免请求的发送者与接收者之间的耦合。责任链模式通过将多个处理对象连接成一条链&#xff0c;使得请求沿着链传递&am…...

20250318在ubuntu20.04中安装向日葵

rootrootrootroot-X99-Turbo:~$ sudo dpkg -i SunloginClient_15.2.0.63064_amd64.deb rootrootrootroot-X99-Turbo:~$ sudo apt-get install -f rootrootrootroot-X99-Turbo:~$ sudo dpkg -i SunloginClient_15.2.0.63064_amd64.deb 20250318在ubuntu20.04中安装向日葵 2025/3…...

Kotlin的 noinline和crossinline关键字

noinline 顾名思义&#xff0c;noinline的意思就是不内联&#xff0c;这个关键字只能作用于内联高阶函数的某个函数类型的参数上&#xff0c;表明当前的函数参数不参与高阶函数的内联&#xff1a; inline fun fun1(doSomething1: () -> Unit, noinline doSomething2: () -&…...

区块链交易签名相关知识总结

基础概念 签名流程 安全相关问题 实际场景 代码示例 进阶问题 一、基础概念 1. 为什么区块链交易需要签名&#xff1f; 答案&#xff1a; 身份认证&#xff1a;证明交易由私钥持有者发起。 数据完整性&#xff1a;确保交易内容未被篡改。 抗抵赖性&#xff1a;签名者无…...

Spring Boot集成Redis并设置密码后报错: NOAUTH Authentication required

报错信息&#xff1a; io.lettuce.core.RedisCommandExecutionException: NOAUTH Authentication required.Redis密码配置确认无误&#xff0c;但是只要使用Redis存储就报这个异常。很可能是因为配置的spring.redis.password没有被读取到。 基本依赖&#xff1a; implementat…...

如何记录Matlab程序运行过程中所占用的最大内存(续)

在上一篇博客中&#xff0c;我们讨论了如何记录Matlab程序运行过程中所占用的最大内存。 博客原文&#xff1a;如何记录Matlab程序运行过程中所占用的最大内存-CSDN博客 但经过测试发现&#xff0c;这与实际有非常大的差异。运行如下例子&#xff1a; clear;clc; profile on…...

分布式节点池:群联云防护抗DDoS的核心武器

一、节点池的核心作用与架构设计 1. 全球分布式节点布局 物理层防御&#xff1a; 根据产品文档&#xff0c;群联在全球部署“海量分布式节点”&#xff0c;每个节点具备独立清洗能力&#xff0c;攻击流量被分散至不同区域节点处理。优势&#xff1a;避免传统单节点防护的瓶颈&…...

Java线程池深度解析:从使用到调优

适合人群&#xff1a;Java中级开发者 | 并发编程入门者 | 系统调优实践者 目录 一、引言&#xff1a;为什么线程池是Java并发的核心&#xff1f; 二、线程池核心知识点详解 1. 线程池核心参数与原理 2. 线程池的创建与使用 (1) 基础用法示例 (2) 内置线程池的隐患 3. 线…...

自动驾驶背后的数学:多模态传感器融合的简单建模

上一篇博客自动驾驶背后的数学:特征提取中的线性变换与非线性激活 以单个传感器为例,讲解了特征提取中的线性变换与非线性激活。 这一篇将以多模态传感器融合为例,讲解稍复杂的线性变换和非线性激活应用场景。 (一)权重矩阵的张量积分解 y = W x + b = [ w 11 ⋯ w 1 n ⋮…...

12 File文件对象:创建、获取基本信息、遍历文件夹、查找文件;字符集的编解码 (黑马Java视频笔记)

文章目录 File >> 存储数据的方案1. 认识File2. File操作2.1 创建File对象2.2 File操作1&#xff09;对文件对象的信息的操作2&#xff09;文件/文件夹的创建/删除3&#xff09;⭐⭐对文件夹的遍历 3. 方法递归3.1 认识递归3.2 递归算法及其执行流程1) 案例&#xff1a;2…...

HTML应用指南:利用GET请求获取猫眼电影日票房信息——以哪吒2为例

2025年春节档期&#xff0c;国产动画电影《哪吒之魔童闹海》&#xff08;以下简称《哪吒2》&#xff09;以颠覆性的叙事风格与工业化制作水准震撼登场&#xff0c;不仅刷新了中国动画电影的票房纪录&#xff0c;更成为全球影史现象级作品。影片凭借春节档期的爆发式开局、持续5…...

荣耀手机卸载应用商店、快应用中心等系统自带的

1.下载abd ADB Download - Get the latest version of ADB and fastboot 2.手机打开开发者选项 3.手机接电脑打开USB调试 4.下载MT管理器查看系统包名 D:\1.LFD\ADB\platform-tools-latest-windows\platform-tools>adb shell adb.exe: no devices/emulators found 这边是…...

[AI速读]用持续集成(CI)优化芯片验证环境:Jenkins与EDA工具的实战指南

在芯片验证中,回归测试(Regression Test)是确保设计稳定性的关键步骤。但随着设计复杂度增加,手动管理海量测试用例、分析日志和覆盖率数据变得异常耗时。本文将介绍如何利用持续集成(CI)工具Jenkins,结合EDA验证环境(如Cadence vManager),实现自动化测试与结果分析,…...

苍穹外卖学习笔记

整体概述 1).用户层 本项目中在构建系统管理后台的前端页面&#xff0c;我们会用到H5、Vue.js、ElementUI、apache echarts(展示图表)等技术。而在构建移动端应用时&#xff0c;我们会使用到微信小程序 2).网关层 Nginx是一个服务器&#xff0c;主要用来作为Http服务器&…...

Spring常用注解汇总

1. IOC容器与Bean管理 注解说明示例Component通用注解&#xff0c;标记类为Spring Bean Component public class MyService { ... } Controller标记Web控制器&#xff08;应用在MVC的控制层&#xff09; Controller public class UserController { ... } Service标记业务逻辑层…...

深度强化学习中的深度神经网络优化策略:挑战与解决方案

I. 引言 深度强化学习&#xff08;Deep Reinforcement Learning&#xff0c;DRL&#xff09;结合了强化学习&#xff08;Reinforcement Learning&#xff0c;RL&#xff09;和深度学习&#xff08;Deep Learning&#xff09;的优点&#xff0c;使得智能体能够在复杂的环境中学…...

每日一题力扣2974.最小数字游戏c++

2974. 最小数字游戏 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:vector<int> numberGame(vector<int>& nums) {vector<int> arr(nums.size());sort(nums.begin(),nums.end());for(size_t i0;i<nums.size();i2){arr[i]nums[i1]…...

软考中级-软件设计师 准备

软考中级-软件设计师 准备 一、软考相关1.1、考试时间1.2、考试时长1.3、题型和分值&#xff1a; 二、软考备考2.1、相关书籍2.2、推荐课程&#xff1a;B站up主zst_20012.3、学习路线 一、软考相关 1.1、考试时间 一年有两次软考&#xff0c;一般是五月末和十一月的中旬 以下…...

EasyRTC嵌入式音视频通信SDK:WebRTC技术下的硬件与软件协同演进,开启通信新时代

在当今数字化时代&#xff0c;智能设备的普及和人们对实时通信需求的不断增长&#xff0c;推动了嵌入式音视频通信技术的快速发。EasyRTC嵌入式音视频通信SDK凭借其独特的技术特点和应用优势&#xff0c;在嵌入式设备和多平台实时通信领域脱颖而出。 1、轻量级设计与高性能 Ea…...

lua垃圾回收

lua垃圾回收 lua 垃圾回收 lua 垃圾回收 collectgarbage(“count”)获取当前lua脚本占用内存字节数(单位为KB)。 collectgarbage(“collect”)执行一次垃圾回收。 xxxnil 将变量置为空&#xff0c;会释放内存。 lua中的机制和c#中回收机制很类似 解除羁绊(置为空)。 --垃圾回…...

Lineageos 22.1(Android 15)实现负一屏

一、前言 方案是参考的这位大佬的&#xff0c;大家可以去付费订阅支持一波。我大概理一下Android15的修改。 大佬的方案代码 二、Android15适配调整 1.bp调整&#xff0c;加入aidl引入&#xff0c;这样make之后就可以索引代码了 filegroup {name: "launcher-src"…...

《深度学习》——YOLOv3详解

文章目录 YOLOv3简介YOLOv3核心原理YOLOv3改进YOLOv3网络结构 YOLOv3简介 YOLOv3&#xff08;You Only Look Once, version 3&#xff09;是一种先进的实时目标检测算法&#xff0c;由 Joseph Redmon 和 Ali Farhadi 开发。它在目标检测领域表现出色&#xff0c;具有速度快、精…...

【设计模式】三十一、状态模式

系列文章|源码 https://github.com/tyronczt/design-mode-learn 文章目录 系列文章|源码一、模式核心思想二、模式结构三、Java代码示例&#xff1a;订单状态管理1. 定义状态接口2. 实现具体状态类3. 上下文类&#xff08;Context&#xff09;4. 客户端调用5. 运行截图 四、状…...

vue 获取当前时间并自动刷新

新增需求&#xff0c;需要在大屏的右上角展示当前时间&#xff0c;并实时按秒刷新&#xff0c;通过通义千问搜索关键js代码后&#xff0c;整理出如下代码。 【效果图】 【HTML】 <div class"time-wrap">{{ formattedDateTime }}<span> {{ weekTime }}&…...

C 语 言 --- 扫 雷 游 戏(初 阶 版)

C 语 言 --- 扫 雷 游 戏 初 阶 版 代 码 全 貌 与 功 能 介 绍扫雷游戏的功能说明游 戏 效 果 展 示游 戏 代 码 详 解game.htest.cgame.c 总结 &#x1f4bb;作 者 简 介&#xff1a;曾 与 你 一 样 迷 茫&#xff0c;现 以 经 验 助 你 入 门 C 语 言 &#x1f4a1;个 人 主…...

WebDeveloper靶机详解

一、主机发现 arp-scan -l靶机ip为192.168.55.163 二、端口扫描、目录枚举、漏洞扫描、指纹识别 2.1端口扫描 nmap --min-rate 10000 -p- 192.168.55.163发现并无特殊端口开放 扫描一下UDP端口 nmap -sU --min-rate 10000 -p- 192.168.55.163没有扫描到UDP端口 2.2目录枚…...

Cursor IDE 入门指南

什么是 Cursor? Cursor 是一款集成了 AI 功能的现代代码编辑器&#xff0c;基于 VSCode 开发&#xff0c;专为提高开发效率而设计。它内置强大的 AI 助手功能&#xff0c;能够理解代码、生成代码、解决问题&#xff0c;帮助开发者更快、更智能地完成编程任务。 基础功能 1.…...

来源于胡椒的亚甲二氧桥CYP450-文献精读119

Piper nigrum CYP719A37 Catalyzes the Decisive Methylenedioxy Bridge Formation in Piperine Biosynthesis 胡椒 (Piper nigrum) CYP719A37 催化胡椒碱生物合成中关键的亚甲二氧桥形成 摘要 胡椒 (Piper nigrum) 是世界上最受欢迎的香料之一。其主要辛辣成分胡椒碱 (piper…...

STM32八股【1】-----启动流程和startup文件理解

启动流程 知识点 MCU 上电复位。MSP从向量表第0个地址读取一个32位&#xff08;2字节&#xff09;的值并保存&#xff0c;该值为栈顶地址。PC计数器从第1个地址读取一个两字节的值并保存&#xff0c;该值为程序入口&#xff0c;一般是Reset_Handler。想了解FLASH地址映射可以…...

Docker与K8S是什么该怎么选?

用了很久的容器化&#xff0c;最近突然看到一个问题问&#xff1a; docker和K8S究竟有什么区别&#xff0c;到底该怎么选&#xff1f;我认真思考了一会&#xff0c;发现一时间还真说不明白&#xff0c;于是就研究了一段时间发布今天的博文&#xff01; Docker vs Kubernetes&a…...