设计模式 行为型 责任链模式(Chain of Responsibility Pattern)与 常见技术框架应用 解析

news2025/1/11 10:52:41

在这里插入图片描述

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许将请求沿着处理者链进行发送。每个处理者对象都有机会处理该请求,直到某个处理者决定处理该请求为止。这种模式的主要目的是避免请求的发送者和接收者之间的耦合关系,从而提高系统的可扩展性和灵活性。

一、核心思想

责任链模式的核心思想是将多个处理器以链式结构连接起来,使请求沿着链传递,直到有一个处理器决定处理此请求。它允许以一种松散耦合的方式组织对象,以便它们可以按顺序处理请求。

二、定义与结构

  • 定义:责任链模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的对象之间像链条一样紧密相连。请求在这个链上传递,直到链上的某一个对象决定处理此请求为止。

  • 结构

    • 请求者(Requester):发起请求的对象。
    • 处理者(Handler):负责处理请求的对象。处理者可以是一个具体的处理器,也可以是一个处理者的集合。每个处理者对象都包含对下一个处理者的引用。
    • 链首处理者(First Handler):链中的第一个处理者,通常也是默认的处理器。
    • 链尾处理者(Last Handler):链中的最后一个处理者,通常用于最终处理请求或作为请求的终结点。

三、角色

在责任链模式中,主要角色包括:

  • 抽象处理者(Handler):定义一个处理请求的接口,并维护一个指向下一个处理者的引用。
  • 具体处理者(Concrete Handler):实现抽象处理者的接口,处理它所负责的请求,并可以访问链中的下一个处理者。如果当前处理者无法处理请求,则将请求传递给下一个处理者。

四、实现步骤及代码示例

以Java为例,展示责任链模式的实现步骤和代码示例:

  1. 定义抽象处理者接口
public abstract class Handler {
    protected Handler next;

    public void setNext(Handler next) {
        this.next = next;
    }

    public abstract void handleRequest(String request);
}
  1. 实现具体处理者类
public class ConcreteHandler1 extends Handler {
    @Override
    public void handleRequest(String request) {
        if ("Request1".equals(request)) {
            System.out.println("ConcreteHandler1 handles Request1");
        } else {
            if (next != null) {
                next.handleRequest(request);
            }
        }
    }
}

public class ConcreteHandler2 extends Handler {
    @Override
    public void handleRequest(String request) {
        if ("Request2".equals(request)) {
            System.out.println("ConcreteHandler2 handles Request2");
        } else {
            if (next != null) {
                next.handleRequest(request);
            }
        }
    }
}
  1. 客户端代码
public class Client {
    public static void main(String[] args) {
        Handler handler1 = new ConcreteHandler1();
        Handler handler2 = new ConcreteHandler2();
        handler1.setNext(handler2);

        Handler chain = handler1;

        chain.handleRequest("Request1"); // 输出: ConcreteHandler1 handles Request1
        chain.handleRequest("Request2"); // 输出: ConcreteHandler2 handles Request2
        chain.handleRequest("Request3"); // 无输出,因为没有处理者能够处理这个请求
    }
}

五、常见技术框架应用

1、以Servlet过滤器链为例

在Java的Servlet中,过滤器(Filter)链就使用了责任链模式。

  • 步骤一:创建过滤器(Filter)
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
// 自定义过滤器1
public class MyFilter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter1执行前");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("MyFilter1执行后");
    }
    @Override
    public void destroy() {
    }
}
// 自定义过滤器2
public class MyFilter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter2执行前");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("MyFilter2执行后");
    }
    @Override
    public void destroy() {
    }
}
  • 步骤二:在web.xml中配置过滤器链
<filter>
    <filter - name>MyFilter1</filter - name>
    <filter - class>MyFilter1</filter - class>
</filter>
<filter - mapping>
    <filter - name>MyFilter1</filter - name>
    <url - pattern>/*</url - pattern>
</filter - mapping>
<filter>
    <filter - name>MyFilter2</filter - name>
    <filter - class>MyFilter2</filter - class>
</filter>
<filter - mapping>
    <filter - name>MyFilter2</filter - name>
    <url - pattern>/*</url - pattern>
</filter - mapping>
  • 当一个请求到达Servlet容器时,会按照过滤器在web.xml中配置的顺序执行。每个过滤器在doFilter方法中可以对请求进行预处理,然后调用filterChain.doFilter方法将请求传递给下一个过滤器或者目标Servlet。最后,在返回响应时,会按照相反的顺序再次经过过滤器。

2、前端框架中的应用

在前端框架中,责任链模式同样可以被应用来实现一些特定的功能。以下是一些责任链模式在前端框架中的应用举例:

事件处理

在前端框架中,事件处理是一个常见的功能。通过使用责任链模式,可以将多个事件处理器连接成一个链条,当某个事件发生时,它会沿着这个链条传递,直到有一个处理器处理它为止。例如,在一个基于Vue.js的Web应用中,可以创建一个事件处理器链条来处理不同类型的用户输入事件(如点击、键盘输入等)。每个处理器都可以根据自己的职责来决定是否处理该事件,或者将事件传递给下一个处理器。

表单验证

在表单提交之前,通常需要进行一系列的验证操作,如检查必填字段、验证邮箱格式等。通过使用责任链模式,可以将这些验证操作组织成一个链条,每个验证器都负责检查一个或多个特定的验证规则。当表单提交时,验证请求会沿着这个链条传递,直到所有验证器都通过或者找到第一个失败的验证器为止。这种方式可以使得表单验证更加灵活和可扩展。

权限控制

在前端应用中,权限控制是一个重要的功能。通过使用责任链模式,可以创建一个权限验证链条,每个验证器都负责检查用户是否具有某个特定的权限。当用户尝试访问某个受保护的资源时,权限验证请求会沿着这个链条传递,直到找到一个验证器允许用户访问或者所有验证器都拒绝为止。这种方式可以使得权限控制更加细粒度和灵活。

综上所述,责任链模式在前端框架中具有广泛的应用前景,可以用于实现事件处理、表单验证、权限控制等功能。通过合理使用责任链模式,可以提高代码的灵活性和可扩展性,降低系统之间的耦合度。

3、其他

在Java中,责任链模式常用于Servlet过滤器(Filter)、Spring AOP中的拦截器等。

六、应用场景

责任链模式通常用于以下场景:

多个对象可能处理一个请求,但具体的处理者事先并不确定。
可动态指定一组对象来处理一个请求。
需要简化对象之间的连接,即减少直接联系。
  1. 请求处理链:当一个请求需要经过多个处理步骤或处理者进行处理时。
  2. 日志记录系统:不同的处理者可以负责不同级别的日志记录。
  3. 身份验证和权限检查系统:每个处理者可以检查特定的条件,如用户名和密码的正确性、账户是否锁定等。
  4. 数据过滤和转换:在数据处理过程中,可以使用责任链模式来进行数据过滤和转换。
  5. 错误处理和异常处理系统:不同的处理者可以处理不同类型的错误或异常。
  6. 事件处理、状态管理等。

七、优缺点

优点

  1. 降低耦合度:责任链模式可以将请求的发送者和接收者解耦,使得请求发送者不需要知道哪个接收者会处理请求。
  2. 灵活性:责任链模式可以动态地组合处理者对象,实现灵活的请求处理过程。
  3. 可扩展性:可以很方便地添加或删除处理者对象,实现责任链的动态调整。
  4. 可维护性:责任链模式可以将复杂的请求处理过程分解为多个简单的处理步骤,并将每个步骤封装在一个处理者对象中,便于维护和扩展。
  5. 提高系统性能:责任链模式可以避免将一个请求发送给所有的接收者,从而提高系统的处理性能。

缺点

  1. 处理不了循环依赖的问题:如果责任链上的处理者对象之间存在循环依赖,就可能导致死循环或者无法正确处理请求。
  2. 可能导致请求得不到处理:如果责任链上的所有处理者对象都无法处理请求,就会导致请求得不到处理,从而浪费系统资源。
  3. 降低系统的稳定性:如果责任链上的某个处理者对象出现故障或者错误,就可能导致整个系统崩溃。此外,由于请求在链中传递,如果链很长,可能会影响处理速度。

综上所述,责任链模式是一种强大的设计模式,它允许以松散耦合的方式组织对象,实现灵活的请求处理过程。然而,在使用时需要注意其潜在的缺点,并采取相应的措施来避免或减轻这些问题。

在这里插入图片描述

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

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

相关文章

VS2022如何修改我们新建工程打开新建文件中,默认输入我们的main函数和宏定义

1.右击我们的VS环境&#xff0c;选择【打开文件位置】 2. 进入C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE 目录 进入【VC】文件夹 进入【VCProjectItems】文件夹 3. 修改newcfile.cpp文件 右击选择【打开方式】选择【记事本】 添加如下内容 #defi…

2025-1-10-sklearn学习(36、37) 数据集转换-无监督降维+随机投影 沙上并禽池上暝。云破月来花弄影。

文章目录 sklearn学习(36、37) 数据集转换-无监督降维随机投影sklearn学习(36) 数据集转换-无监督降维36.1 PCA: 主成份分析36.2 随机投影36.3 特征聚集 sklearn学习(37) 数据集转换-随机投影37.1 Johnson-Lindenstrauss 辅助定理37.2 高斯随机投影37.3 稀疏随机矩阵 sklearn学…

openssl编译

关于windows下&#xff0c;openssl编译 环境准备 安装 perl:https://djvniu.jb51.net/200906/tools/ActivePerl5_64.rar安装nasm&#xff1a;https://www.nasm.us/pub/nasm/releasebuilds/2.13.01/win64/nasm-2.13.01-installer-x64.exe下载opensll源码&#xff1a;https://o…

2025-1-9 QT 使用 QXlsx库 读取 .xlsx 文件 —— 导入 QXlsx库以及读取 .xlsx 的源码 实践出真知,你我共勉

文章目录 1. 导入QXlsx库2. 使用 QXlsx库 读取 .xlsx 文件小结 网上有很多教程&#xff0c;但太费劲了&#xff0c;这里有个非常简便的好方法&#xff0c;分享给大家。 1. 导入QXlsx库 转载链接 &#xff1a;https://github.com/QtExcel/QXlsx/blob/master/HowToSetProject.md…

先辑芯片HPM5300系列之SEI多摩川协议命令表问题研究

多摩川协议有9条命令&#xff0c;但是先辑SEI的命令表只有8张。0-6是可用的&#xff0c;第7张是黑洞表&#xff0c;所以只有7张可用。 命令表的限制颇多&#xff0c;比如命令表只能按顺序使用 &#xff1a;例如0、1、3&#xff0c;那么命令表3是不能用的。 如果想要实现9个命令…

kotlin项目无法访问Java类的问题

使用IntelliJ创建一个Kotlin项目&#xff0c;然后在src/main/kotlin中创建一个java接口&#xff1a;Animal.java&#xff0c;然后在Main.kt中打印这个java接口&#xff0c;如下&#xff1a; fun main() {println(Animal::class.java) }代码在编辑器中并没有报错&#xff0c;但…

全栈面试(一)Basic/微服务

文章目录 项目地址一、Basic InterviewQuestions1. tell me about yourself?2. tell me about a time when you had to solve a complex code problem?3. tell me a situation that you persuade someone at work?4. tell me a about a confict with a teammate and how you…

医疗可视化大屏 UI 设计新风向

智能化交互 借助人工智能与机器学习技术&#xff0c;实现更智能的交互功能。如通过语音指令或手势控制来操作大屏&#xff0c;医护人员无需手动输入&#xff0c;可更便捷地获取和处理信息。同时&#xff0c;系统能根据用户的操作习惯和数据分析&#xff0c;自动推荐相关的医疗…

Angular由一个bug说起之十三:Cross Origin

跨域 想要了解跨域&#xff0c;首要要了解源 什么是源&#xff0c;源等于协议加域名加端口号 只有这三个都相同&#xff0c;才是同源&#xff0c;反之则是非同源。 比如下面这四个里&#xff0c;只有第4个是同源 而浏览器给服务器发送请求时&#xff0c;他们的源一样&#xff0…

【LeetCode Hot100 贪心算法】 买卖股票的最佳时机、跳跃游戏、划分字母区间

贪心算法 买卖股票的最佳时机买卖股票的最佳时机II跳跃游戏跳跃游戏II划分字母区间 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的…

MCANet: 基于多模态字幕感知的大语言模型训练无关视频异常检测

目录 摘要01 引言02 相关工作2.1 视频异常检测2.2 基于视频的大语言模型&#xff08;VLLMs&#xff09; 03 方法论3.1 问题定义3.2 MCANet3.3 图像字幕分支3.4 音频字幕分支3.5 基于LLM的异常评分3.6 视频-文本分数优化 04 实验4.1 数据集和评估指标4.2 实现细节4.3 定性结果4.…

为深度学习引入张量

为深度学习引入张量 什么是张量&#xff1f; 神经网络中的输入、输出和转换都是使用张量表示的&#xff0c;因此&#xff0c;神经网络编程大量使用张量。 张量是神经网络使用的主要数据结构。 张量的概念是其他更具体概念的数学概括。让我们看看一些张量的具体实例。 张量…

Taro+Vue实现图片裁剪组件

cropper-image-taro-vue3 组件库 介绍 cropper-image-taro-vue3 是一个基于 Vue 3 和 Taro 开发的裁剪工具组件&#xff0c;支持图片裁剪、裁剪框拖动、缩放和输出裁剪后的图片。该组件适用于 Vue 3 和 Taro 环境&#xff0c;可以在网页、小程序等平台中使用。 源码 https:…

[DO374] Ansible 配置文件

[DO374] Ansible 配置文件 1. 配置文件位置2. 配置文件3. Ansible 配置4. Ansible的Ad-hoc5. Ansible 模块6. playbook段落7. 任务执行后续8. Ansible 变量8.1 ansible 变量的定义8.1.1 主机变量8.1.2 主机组变量 8.2 vars的循环 9. Ansible Collection10. Ansible-galaxy 安装…

[程序设计]—代理模式

[程序设计]—代理模式&#x1f473; 本文章记录学习于——52.面向切面&#xff1a;AOP-场景模拟_哔哩哔哩_bilibili 最近闲来无事&#xff0c;在学习Spring的源码&#xff1a; 后面慢慢更新源码系列blog&#xff0c;希望多多关注&#x1f64f;&#x1f64f; 目前已经总结的b…

OSPF - 2、3类LSA(Network-LSA、NetWork-Sunmmary-LSA)

前篇博客有对常用LSA的总结 2类LSA&#xff08;Network-LSA&#xff09; DR产生泛洪范围为本区域 作用:  描述MA网络拓扑信息和网络信息&#xff0c;拓扑信息主要描述当前MA网络中伪节点连接着哪几台路由。网络信息描述当前网络的 掩码和DR接口IP地址。 影响邻居建立中说到…

景芯SOC设计实战

终身辅导、一对一辅导&#xff0c;手把手教您完成SoC全流程设计&#xff0c;从入门到进阶&#xff0c;带您掌握SoC芯片架构、算法、设计、验证、DFT、后端及低功耗全流程&#xff01;直播视频不定期升级&#xff01;让您快速超越同龄人&#xff01; 景芯团队主打文档服务器实战…

多云架构,JuiceFS 如何实现一致性与低延迟的数据分发

随着大模型的普及&#xff0c;GPU 算力成为稀缺资源&#xff0c;单一数据中心或云区域的 GPU 资源常常难以满足用户的全面需求。同时&#xff0c;跨地域团队的协作需求也推动了企业在不同云平台之间调度数据和计算任务。多云架构正逐渐成为一种趋势&#xff0c;然而该架构下的数…

如何获取文件的MIME类型

文章目录 1. 概念介绍2. 方法与类型2.1 使用方法2.2 常见类型3. 示例代码4. 内容总结我们在上一章回中介绍了"如何加载本地图片"相关的内容,本章回中将介绍如何获取文件类型.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章回中提到的文件类型是指MI…

【Uniapp-Vue3】computed计算属性用法及方法对比

如果我们想要将两个响应式变量进行某种运算&#xff0c;就可以使用computed计算属性。 比如下面这个例子中&#xff0c;输入名和姓合成全名&#xff0c;可以用直接显示的方法&#xff1a; 我们也可以使用computed属性&#xff1a; import {computed} from "vue"; le…