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

Java 责任链模式详解

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它用于将请求的发送者和接收者解耦,使得多个对象都有机会处理这个请求。在责任链模式中,有一个请求处理链条,每个处理请求的对象都是一个节点,当请求进入这个链条时,链条上的节点逐一判断是否能够处理该请求,如果可以,则处理;否则,将请求传递给下一个节点,直到请求被处理为止。

责任链模式可以有效地避免请求发送者与接收者之间的耦合,将请求处理对象按照顺序串联起来形成一个链条,每个节点都可以根据自己的职责进行处理,可以动态地增加、删除或修改节点。责任链模式常用于处理请求的场景,例如登录验证、权限校验、日志记录、异常处理等。

本文将详细介绍 Java 中的责任链模式,包括其概念、结构、实现方式以及应用案例等,帮助读者更好地理解和应用责任链模式。

一、概念

责任链模式定义了一个请求处理对象的链条,每个对象都可以处理请求或者将请求转发给下一个对象,直到有一个对象处理请求为止。在责任链模式中,请求发送者不需要知道链条中具体的处理对象,只需要将请求发送给链头即可,具体的处理过程和实现细节由链条中的对象来决定。责任链模式可以有效地解耦请求发送者和接收者,分离职责,提高系统的灵活性和可维护性。

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

  • Handler(处理者):定义了处理请求的接口,通常包含一个抽象方法或者一个处理请求的抽象类。每个处理者都知道自己的后继者(下一个处理者),如果自己不能处理该请求,则将其转发给后继者。
  • ConcreteHandler(具体处理者):实现了 Handler 接口,并对请求进行实际处理。每个具体处理者都能够处理一些特定的请求类型,如果自己不能处理该请求,则将其转发给后继者。
  • Client(客户端):创建链条的起点,向链条头部的处理者发送请求。

二、结构

责任链模式的结构比较简单,主要包括以下几个部分:

在这里插入图片描述
其中,Handler 是一个抽象类或接口,定义了处理请求的方法 handleRequest() 和设置后继节点的方法 setSuccessor()。ConcreteHandler 类继承了 Handler 并实现了 handleRequest() 方法,在方法中判断是否能够处理该请求,如果能够处理则进行处理;否则将请求转发给下一个处理者。Client 类创建责任链的头部(即第一个 ConcreteHandler 对象),并向它发送请求。

三、实现方式

  1. 单向链表实现

单向链表是最常见的责任链模式实现方式,具有以下特点:

  • 链表中节点的处理顺序与其添加顺序相同。
  • 可以动态添加、删除或修改节点。

单向链表实现的核心代码如下:

public abstract class Handler {private Handler successor;  // 后继节点public void setSuccessor(Handler successor) {this.successor = successor;}// 处理请求的抽象方法public abstract void handleRequest(Request request);protected void next(Request request) {if (successor != null) {  // 如果有后继节点,则转发请求successor.handleRequest(request);}}
}public class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(Request request) {if (canHandle(request)) {  // 判断是否能够处理该请求// 处理请求} else {next(request);  // 转发请求给下一个处理者}}private boolean canHandle(Request request) {// 判断是否能够处理该请求的逻辑}
}public class Client {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setSuccessor(handlerB);  // 设置后继节点Request request = new Request();handlerA.handleRequest(request);  // 发送请求到链头}
}
  1. 数组或队列实现

除了单向链表,还可以使用数组或队列等数据结构来实现责任链模式,主要思想是将处理者放在一个数组或队列中按序存储。这种实现方式比较简单,但不够灵活,并且不支持动态添加、删除或修改节点。

数组或队列实现的核心代码如下:

public abstract class Handler {// ...// 处理请求的抽象方法public abstract void handleRequest(Request request);protected void next(Request request, Handler[] handlers, int index) {if (index < handlers.length) {  // 如果有后继节点,则转发请求handlers[index].handleRequest(request);}}
}public class Client {public static void main(String[] args) {Handler[] handlers = new Handler[] {new ConcreteHandlerA(), new ConcreteHandlerB()};Request request = new Request();handlers[0].handleRequest(request, handlers, 1);  // 发送请求到链头}
}

四、应用案例

责任链模式在Java中有许多应用场景,例如:

  1. 过滤器(Filter):在Servlet中,过滤器就是使用责任链模式实现的。每个过滤器都可以决定是否处理请求,或者将其转发给下一个过滤器进行处理。

  2. 拦截器(Interceptor):在Spring框架中,拦截器就是使用责任链模式实现的。拦截器可以对请求进行预处理或后处理,也可以将请求转发给下一个拦截器进行处理。

  3. 异常处理(Exception Handling):在Java中,可以使用责任链模式来处理异常。首先,程序先尝试使用自定义的异常处理器来处理异常,如果该处理器无法处理异常,则将其转发给下一个处理器进行处理。

  4. 日志记录(Logger):在Java中,可以使用责任链模式来记录日志。每个日志记录器都可以决定是否需要记录该日志,或者将其转发给下一个日志记录器进行记录。

五、总结

责任链模式是一种常见的设计模式,在Java中有多种实现方式。通过责任链模式,可以将请求发送者和接收者解耦,提高系统的灵活性和可维护性。在实际应用中,可以将责任链模式应用于过滤器、拦截器、异常处理、日志记录等场景,从而实现统一的处理逻辑。

相关文章:

Java 责任链模式详解

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;它用于将请求的发送者和接收者解耦&#xff0c;使得多个对象都有机会处理这个请求。在责任链模式中&#xff0c;有一个请求处理链条&#xff0c;每个处理请求的对象都是一个…...

使用MASA全家桶从零开始搭建IoT平台(三)管理设备的连接状态

文章目录 前言分析方案1:遗嘱消息演示遗嘱消息的使用实施流程 方案2:使用WebHook开启WebHook演示Webhook编写代码 前言 获取一个设备的在线和离线状态&#xff0c;是一个很关键的功能。我们对设备下发的控制指令&#xff0c;设备处于在线状态才能及时给我们反馈。这里的在线和…...

我的新书上架了!

talk is cheap&#xff0c;show you my book&#xff01; 新书《从0开始学ARM》终于在各大平台上架了&#xff01;&#xff01; 一、关于本书 1. 本书主要内容 ARM体系架构是目前市面上的主流处理器体系架构&#xff0c;在手机芯片和嵌入式芯片领域&#xff0c;ARM体系架构…...

语言与专业的奇迹:如何利用ChatGPT优化跨国贸易

贸易公司&#xff0c;在进行跨国贸易时&#xff0c;往往需要面对不同国家的甲方或者乙方&#xff0c;在与之沟通的过程中&#xff0c;语言和专业是必须要过的一关&#xff0c;顺畅的交流&#xff0c;往往会带来更好的收益。 今天以“茶”为例&#xff0c;给大家介绍一“知否AI…...

云服务器安装宝塔Linux面板命令脚本大全

阿里云服务器安装宝塔Linux面板&#xff0c;操作系统不同安装命令脚本也不同&#xff0c;支持CentOS、Alibaba Cloud Linux、Ubuntu/Deepin等Linux系统&#xff0c;阿里云服务器网分享阿里云服务器安装宝塔Linux面板命令脚本大全&#xff1a; 云服务器安装宝塔Linux面板命令 …...

zed2i相机中imu内参的标定及外参标定

zed2i中imu内参的标定 参考&#xff1a; https://blog.csdn.net/weixin_42681311/article/details/126109617 https://blog.csdn.net/weixin_43135184/article/details/123444090 值得注意&#xff0c;imu内参的标定其实不是那么重要&#xff0c;大致上给一个值应该影响不大…...

Java中的JUnit是什么?如何使用JUnit进行单元测试

JUnit是Java中最流行的单元测试框架之一。它可以帮助开发人员在代码编写过程中检测出错误和异常&#xff0c;从而提高代码的质量和可靠性。 什么是JUnit&#xff1f; JUnit是一个由Kent Beck和Erich Gamma创建的开源Java单元测试框架&#xff0c;它已经成为Java开发中最常用的…...

【seata的部署和集成】

seata的部署和集成 seata的部署和集成一、部署Seata的tc-server1.下载2.解压3.修改配置4.在nacos添加配置5.创建数据库表6.启动TC服务 二、微服务集成seata1.引入依赖2.修改配置文件 三、TC服务的高可用和异地容灾1.模拟异地容灾的TC集群2.将事务组映射配置到nacos3.微服务读取…...

uniapp学习日记之request自定义请求头

uniapp学习日记之request自定义请求头 在学习uniapp的过程中&#xff0c;由于笔者是从Vue项目转来学习uniapp&#xff0c;在使用uni.request时&#xff0c;发现在浏览器调试时&#xff0c;无法在请求头header中添加token字段&#xff0c;愤而弃之&#xff0c;便开始使用axios组…...

【Rust】速度入门---打印个螃蟹先

参考: 菜鸟教程 1 输出到命令行 这不得打印个螃蟹 // 代码来自官方入门教程 // ferris_say需要另外安装 use ferris_says::say; use std::io::{stdout, BufWriter};fn main() {let stdout: std::io::Stdout stdout();let msg: String String::from("Hello fellow Rusta…...

《Linux 内核设计与实现》12. 内存管理

文章目录 页区获得页获得填充为 0 的页释放页 kmalloc()gfp_mask 标志kfree()vmalloc() slab 层slab 层的设计slab 分配器的接口 在栈上的静态分配单页内核栈 高端内存的映射永久映射临时映射 每个 CPU 的分配新的每个 CPU 接口 页 struct page 结构表示系统中的物理页&#x…...

公司新来个卷王,让人崩溃...

最近内卷严重&#xff0c;各种跳槽裁员&#xff0c;相信很多小伙伴也在准备今年的面试计划。 在此展示一套学习笔记 / 面试手册&#xff0c;年后跳槽的朋友可以好好刷一刷&#xff0c;还是挺有必要的&#xff0c;它几乎涵盖了所有的软件测试技术栈&#xff0c;非常珍贵&#x…...

Docker 安全及日志管理

Docker 安全及日志管理 Docker 容器与虚拟机的区别隔离与共享性能与损耗 Docker 存在的安全问题Docker 自身漏洞Docker 源码问题Docker 架构缺陷与安全机制Docker 安全基线标准 容器相关的常用安全配置方法容器最小化Docker 远程 API 访问控制重启 Docker在宿主机的 firewalld …...

大厂面试必备 - MAC 地址 和 IP 地址分别有什么作用?

数据链路层 1、MAC 地址 和 IP 地址分别有什么作用&#xff1f; MAC 地址是数据链路层和物理层使用的地址&#xff0c;是写在网卡上的物理地址。MAC 地址用来定义网络设备的位置。IP 地址是网络层和以上各层使用的地址&#xff0c;是一种逻辑地址。IP 地址用来区别网络上的计…...

【sqlite】联查Join更新

系列文章 C#底层库–MySQLBuilder脚本构建类&#xff08;select、insert、update、in、带条件的SQL自动生成&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129179216 C#底层库–MySQL数据库操作辅助类&#xff08;推荐阅读&#xff0…...

asp.net+C#德育课程分数统计管理系统

本中小学德育管理系统主要学校内部提供服务&#xff0c;系统分为管理员&#xff0c;教师和学生3个大模块。 本研究课题重点主要包括了下面几大模块&#xff1a;用户登录&#xff0c;管理员信息管理学生信息管理&#xff0c;教师信息管理&#xff0c;班级成绩管理&#xff0c;学…...

Figma中文网?比Figma更懂你的设计网站!

一个比 Figma 更懂你的设计网站的 Figma 中文网 —— 即时设计是一个非常有用的设计资源平台&#xff0c;它提供了大量的免费设计素材&#xff0c;包括来自各大厂商的 UI 组件库、精美的模板、插画设计和矢量图标素材等等。设计师可以从中学习到大师的设计技巧和规范&#xff0…...

Nacos-01-Nacos基本介绍

背景 ​ 服务发现是⼀个古老的话题&#xff0c;当应用开始脱离单机运行和访问时&#xff0c;服务发现就诞生了。目前的网络架构是每个主机都有⼀个独立的 IP 地址&#xff0c;那么服务发现基本上都是通过某种方式获取到服务所部署的 IP 地址。DNS 协议是最早将⼀个网络名称翻译…...

SpringBoot集成Dubbo启用gRPC协议

文章目录 前言项目结构代码示例父工程api moduleservice module 注意事项区别 本文记录下SpringBoot集成Dubbo启用gRPC协议&#xff0c;以及与原生 gRPC 在代码编写过程中的区别。 下面还有投票&#xff0c;帮忙投个票&#x1f44d; 前言 Dubbo 在 2.7.5 版本开始支持原生 gRP…...

Kali HTTrack演示-渗透测试察打一体(1)

HTTrack是一个免费并易于使用的线下浏览器工具,全称是HTTrack Website Copier for Windows,它能够让你从互联网上下载指定的网站进行线下浏览(离线浏览),也可以用来收集信息(甚至有网站使用隐藏的密码文件),一些仿真度极高的伪网站(为了骗取用户密码),也是使用类似工具做…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

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 提…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...