Java 责任链模式详解

news2024/11/25 16:50:47

责任链模式(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 {
    @Override
    public 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中有多种实现方式。通过责任链模式,可以将请求发送者和接收者解耦,提高系统的灵活性和可维护性。在实际应用中,可以将责任链模式应用于过滤器、拦截器、异常处理、日志记录等场景,从而实现统一的处理逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/513855.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql数据库基础知识,mysql数据库简介(一看就懂,一学就会)

目录 一、MySQL学习路线二、MySQL常见操作1、查看所有数据库show databases。2、MySQL 创建数据库3、删除数据库4、选择数据库use databasename5、查看该数据库下所有表show tables6、创建数据库表7、删除数据库 三、增删改查1、插入数据2、查询数据3、where子句4、更新语句5、…

微前端应用(qiankun+umi+antd)

1.微前端介绍以应用选型 1.1什么是微前端? 微前端是一种前端架构模式&#xff0c;它将前端应用程序拆分成多个小型的、独立开发、独立部署的子应用&#xff0c;然后将这些子应用组合成一个大型的、复杂的前端应用。每个子应用都有自己的技术栈、独立的代码库、独立的开发、测…

Linux快捷命令

目录 一、快捷排序——sort 常用选项&#xff1a; 示例 二、快捷去重——uniq 常用选项&#xff1a; 示例&#xff1a; ​编辑 ​编辑 ​编辑 三、快捷替换——tr 用于windows的编写的脚本格式转换为Linux格 方法一&#xff1a; 方法二&#xff1a; 四、快速裁…

JAVA double精度丢失问题

double类型精度丢失问题&#xff1a; 0.1*0.1使用计算器计算是0.01&#xff0c;代码里却是0.010000000000000002 public class HelloWorld {public static void main(String []args) {double number1 0.1;double number2 0.1;double result number1 * number2 ;System.o…

CSP-S 2022 提高级 第一轮 阅读程序(1) 第16-21题

【题目】 CSP-S 2022 提高级 第一轮 阅读程序&#xff08;1&#xff09; 第16-21题 01 #include <iostream> 02 #include <string> 03 #include <vector> 04 05 using namespace std; 06 07 int f(const string &s, const string &t) 08 { …

关于cartographer建立正确关系树的理解

正确的TF关系map----odom----base_link----laser base_link是固定在机器人本体上的坐标系&#xff0c;通常选择飞控 其中map–odom 的链接是由cartographer中lua文件配置完成的 map_frame "map", tracking_frame "base_link", published_frame "b…

Ubuntu 20.04 安装 mysql8 并配置远程访问

文章目录 一、使用 apt-get 安装 mysql 服务二、初始化 mysql 数据库管理员用户密码三、配置远程访问 一、使用 apt-get 安装 mysql 服务 # 更新软件源 apt-get install update# 安装mysql服务 apt-get install mysql-server# 使用mysqladmin工具查看mysql版本 mysqladmin --v…

一文解析Linux进程的睡眠和唤醒

Linux进程的睡眠和唤醒 在Linux中&#xff0c;仅等待CPU时间的进程称为就绪进程&#xff0c;它们被放置在一个运行队列中&#xff0c;一个就绪进程的状 态标志位为 TASK_RUNNING。一旦一个运行中的进程时间片用完&#xff0c; Linux 内核的调度器会剥夺这个进程对CPU的控制权&…

燃气巡检二维码

对燃气公司的输气管道和阀井等设施的巡检工作的管理目标是能降低成本、提高工作效率以及管理水平。但用纸质记录的方式进行燃气设备巡检有以下缺点&#xff1a; 1、难保证巡检真实性 无法客观、方便地掌握巡检人员巡检的到位情况&#xff0c;因而无法有效地保证巡检工作人员按计…

软件兼容性测试如何进行?怎么选择靠谱的软件检测公司?

软件兼容性测试是一项非常重要的工作&#xff0c;能够确保在不同的操作系统、设备、浏览器以及其他软件环境下&#xff0c;软件应用都能够正常运行。 一、软件兼容性测试如何进行? 确定测试的环境&#xff0c;包括操作系统、设备、浏览器等&#xff0c;并建立测试用例和测试…

Maven必要知识

参考笔记&#xff1a; https://www.wolai.com/arAiYJYCr6Kkfi2kZ8HxE8 1. Maven 概述 1.1 什么是 Maven Maven 是 Apache 软件基金会组织维护的一款专门为 Java 项目提供构建和依赖管理支持的工具。 Maven 作为依赖管理工具 jar 包的管理jar 包的来源jar 包之间的依赖关系…

使用R语言绘制折线图

R语言绘制折线图 一、绘制折线图1.载入bruceR&#xff08;ggplot2&#xff09;2.设置当前工作目录3.载入数据集4.查看数据结构5.绘制基础图形6.图形优化 二、绘制多重折线图1.载入数据2.绘制图形 一、绘制折线图 1.载入bruceR&#xff08;ggplot2&#xff09; &#xff08;要…

【HAL库】STM32CubeMX开发----非阻塞延时实验----SysTick(滴答定时器)中断

STM32CubeMX 下载和安装 详细教程 【HAL库】STM32CubeMX开发----STM32F103/F207/F407----目录 前言 HAL库 有自带的 ms级 延时函数&#xff1a; HAL_Delay(); 缺点&#xff1a; 这是阻塞延时方式&#xff0c;就是延时期间&#xff0c;什么都不能干&#xff0c;这样很浪费资源。…

便携式车用CAN分析仪

产品简介 USBCAN-C系列便携式车用CAN分析仪&#xff0c;通过USB接口快速扩展一路CAN通道&#xff0c;使接入CAN网络非常容易&#xff0c;它具有一体式和小巧紧凑的外形&#xff0c;特别适合于随身携带。CAN接口采用金升阳电源模块和信号隔离芯片实现2500V DC电气隔离&#xff0…

能源设备智能维修AR远程作业指导平台降低运营成本

AR远程专家指导系统是一种基于AR增强现实技术搭建的远程协作解决方案&#xff0c;它可以让专家全视角掌握操作现场&#xff0c;并将专精知识和技能传递给远程现场的工作人员&#xff0c;以帮助他们解决各种技术难题和困难&#xff0c;赋能各行各业行业。 现场人员通过手机、平板…

OJ练习第104题——格雷编码

格雷编码 力扣链接&#xff1a;89. 格雷编码 题目描述 n 位格雷码序列 是一个由 2n 个整数组成的序列&#xff0c;其中&#xff1a; 每个整数都在范围 [0, 2n - 1] 内&#xff08;含 0 和 2n - 1&#xff09; 第一个整数是 0 一个整数在序列中出现 不超过一次 每对 相邻 整数…

数据流图(DFD)这么理解吗?

如何画好数据流程图&#xff08;DFD&#xff09;&#xff1f; 步骤&#xff1a; 确定系统的 input 和 output。由 表层 到 深层 画系统的顶层数据流图。自顶向下 逐层 分解&#xff0c;画出分层数据流图。 一、理解数据流图 基本概念 ~~ 数据流图 数据流&#xff08;箭头&…

linux pinctrl 和 gpio 子系统 LED驱动

pinctrl 和 gpio 子系统 借助 pinctrl 和 gpio 子系统来简化 GPIO 驱动开发 pinctrl 子系统 pinctrl 子系统&#xff08;drivers/pinctrl&#xff09;的主要工作内容&#xff1a; ①、获取设备树中 pin 信息。 ②、根据获取到的 pin 信息来设置 pin 的复用功能 ③、根据获…

校招失败后,4面字节跳动软件测试工程师,竭尽全力....

下面是我面试字节跳动软件测试工程师的面试经验总结&#xff0c;希望能帮助到你们。 面试一 简单做一下自我介绍简要介绍一下项目/你负责的模块/选一个模块说一下你设计的用例get请求和post请求的区别如何判断前后端bug/3xx是什么意思说一下XXX项目中你做的接口测试/做了多少次…

免费润色文章的软件-自动修改文章润色的软件

免费润色文章的软件 免费润色文章的软件可以帮助用户快速地改善文本质量&#xff0c;进一步提高语言表达能力和流畅性&#xff0c;以下是其主要优势&#xff1a; 高效性&#xff1a;免费润色文章的软件能够快速进行润色处理&#xff0c;为用户节省时间和精力。相比手动润色的方…