设计模式教程:责任链模式(Chain of Responsibility Pattern)

责任链模式(Chain of Responsibility Pattern)是一种常用的设计模式,它属于行为型模式,主要解决的是多个对象处理一个请求时,如何解耦请求的发送者和接收者,以及如何将请求的处理职责分配给不同的对象。

1. 责任链模式的定义:

责任链模式使得多个对象有机会处理请求,而不是由一个对象来处理请求。每个处理者都有一个指向下一个处理者的指针,当一个请求到达某个处理者时,它会决定自己是否能够处理该请求,如果能够处理就处理,否则将请求传递给下一个处理者。

2. 责任链模式的结构:

  • Handler(处理者):这是一个抽象类或接口,定义了处理请求的方法,通常是一个抽象方法 handleRequest(),并且通常会有一个指向下一个处理者的引用(即链条中的下一个对象)。

  • ConcreteHandler(具体处理者):每个具体的处理者类都实现了处理请求的逻辑。如果当前处理者不能处理该请求,它会将请求传递给链中的下一个处理者。具体处理者通常会根据某些条件判断是否能够处理请求。

  • Client(客户端):客户端负责将请求发送到链中的第一个处理者。客户端不关心请求如何被处理,只是把请求交给责任链的第一个处理者。

3. 责任链模式的流程:

  1. 客户端发送请求:客户端把请求交给链中的第一个处理者。
  2. 处理者判断是否能处理请求:每个处理者都可以根据自己的能力判断自己是否能处理这个请求。如果处理者能处理,则处理请求;否则,将请求传递给链中的下一个处理者。
  3. 继续传递请求:如果没有处理者能够处理请求,那么请求就会被完全传递出去,或者返回错误。

4. 责任链模式的优点:

  • 解耦请求的发送者和接收者:客户端不需要知道具体哪个处理者会处理请求,只是将请求交给责任链的第一个处理者,后续的责任链内部如何处理不需要关心。
  • 灵活性高:可以动态添加处理者。通过修改链中的处理者顺序或者添加新的处理者,可以很方便地改变处理流程。
  • 责任的分配更加清晰:每个处理者只需要关心自己能处理的任务,而不必了解整个请求的处理过程。

5. 责任链模式的缺点:

  • 性能问题:如果责任链过长,请求可能需要在链中传递很久,这会影响性能。
  • 责任链复杂:当责任链中有很多处理者时,维护责任链的代码可能变得复杂,尤其是当责任链变化频繁时。
  • 请求丢失问题:如果没有任何处理者处理请求,可能会导致请求丢失或者处理失败。

6. 责任链模式的示例:

6.1 简单的责任链实现

假设我们有三个不同的处理者,需要对请求进行处理,处理规则如下:

6.3 责任链模式的优化:

  • 请求的数字小于 10 由 ConcreteHandler1 处理。
  • 请求的数字介于 10 和 20 之间由 ConcreteHandler2 处理。
  • 请求的数字大于 20 由 ConcreteHandler3 处理。
    // Handler 抽象类
    abstract class Handler {protected Handler nextHandler; // 下一个处理者public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public abstract void handleRequest(int request);
    }// ConcreteHandler1
    class ConcreteHandler1 extends Handler {@Overridepublic void handleRequest(int request) {if (request < 10) {System.out.println("ConcreteHandler1 handles request " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
    }// ConcreteHandler2
    class ConcreteHandler2 extends Handler {@Overridepublic void handleRequest(int request) {if (request >= 10 && request < 20) {System.out.println("ConcreteHandler2 handles request " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
    }// ConcreteHandler3
    class ConcreteHandler3 extends Handler {@Overridepublic void handleRequest(int request) {if (request >= 20) {System.out.println("ConcreteHandler3 handles request " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
    }// Client
    public class Client {public static void main(String[] args) {Handler handler1 = new ConcreteHandler1();Handler handler2 = new ConcreteHandler2();Handler handler3 = new ConcreteHandler3();// 设置责任链handler1.setNextHandler(handler2);handler2.setNextHandler(handler3);// 处理请求int[] requests = {5, 15, 25, 30};for (int request : requests) {handler1.handleRequest(request);}}
    }
    

    输出:

    ConcreteHandler1 handles request 5
    ConcreteHandler2 handles request 15
    ConcreteHandler3 handles request 25
    ConcreteHandler3 handles request 30
    
    6.2 责任链模式的应用场景
  • 日志处理:不同级别的日志(如调试、信息、警告、错误)可以通过责任链来处理,不同级别的日志传递给不同的处理者。
  • 用户请求处理:比如在电商系统中,用户的请求(如订单支付、退货申请等)可以通过责任链传递,处理者可以根据请求类型、用户权限等进行不同的处理。
  • 权限校验:多个权限校验规则可以通过责任链模式处理,用户请求可以依次通过不同的校验器。
  • 添加缓存机制:如果请求传递链很长,可以为请求的处理结果添加缓存,避免重复处理。
  • 提前终止链条:如果某个处理者已经完成了请求处理,可以选择终止责任链,避免继续传递。
    版权声明

7. 总结

责任链模式通过将请求传递给链中的多个处理者,让请求的处理变得灵活且可扩展。通过责任链,我们可以轻松添加或移除处理者,从而无需更改客户端代码。对于那些有多种不同处理方式的请求,责任链模式是一个非常有效的设计方案。

版权声明
  1. 本文内容属于原创,欢迎转载,但请务必注明出处和作者,尊重原创版权。
  2. 转载时,请附带原文链接并注明“本文作者:扣丁梦想家
  3. 禁止未经授权的商业转载。

如果您有任何问题或建议,欢迎留言讨论。

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

        如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

        相关文章

        Scala基础学习

        主要用来处理数据&#xff0c;不处理web&#xff0c;没有类似spring的框架 1. Scala简介 我们基于的scala版本 2.12.10 scala是运行在 JVM 上的多范式&#xff08;规范&#xff09;编程语言&#xff0c;同时支持面向对象和面向函数编程。&#xff08;真实数据与操作过程解耦…

        贪心算法

        int a[1000], b5, c8; swap(b, c); // 交换操作 memset(a, 0, sizeof(a)); // 初始化为0或-1 引导问题 为一个小老鼠准备了M磅的猫粮&#xff0c;准备去和看守仓库的猫做交易&#xff0c;因为仓库里有小老鼠喜欢吃的五香豆&#xff0c;第i个房间有J[i] 磅的五香豆&#xf…

        复现论文:DPStyler: Dynamic PromptStyler for Source-Free Domain Generalization

        论文&#xff1a;[2403.16697] DPStyler: Dynamic PromptStyler for Source-Free Domain Generalization github: TYLfromSEU/DPStyler: DPStyler: Dynamic PromptStyler for Source-Free Domain Generalization 论文: 这篇论文还是在PromptStyler:Prompt-driven Style Gener…

        AI 编程助手 cursor的系统提示词 prompt

        # Role 你是一名极其优秀具有10年经验的产品经理和精通java编程语言的架构师。与你交流的用户是不懂代码的初中生&#xff0c;不善于表达产品和代码需求。你的工作对用户来说非常重要&#xff0c;完成后将获得10000美元奖励。 # Goal 你的目标是帮助用户以他容易理解的…

        TikTok账户安全指南:如何取消两步验证?

        TikTok账户安全指南&#xff1a;如何取消两步验证&#xff1f; 在这个数字化的时代&#xff0c;保护我们的在线账户安全变得尤为重要。TikTok&#xff0c;作为全球流行的社交媒体平台&#xff0c;其账户安全更是不容忽视。两步验证作为一种增强账户安全性的措施&#xff0c;虽…

        详解分布式ID实践

        引言 分布式ID&#xff0c;所谓的分布式ID&#xff0c;就是针对整个系统而言&#xff0c;任何时刻获取一个ID&#xff0c;无论系统处于何种情况&#xff0c;该值不会与之前产生的值重复&#xff0c;之后获取分布式ID时&#xff0c;也不会再获取到与其相同的值&#xff0c;它是…

        react 踩坑记 too many re-renders.

        报错信息&#xff1a; too many re-renders. React limits the number of randers to prevent an infinite loop. 需求 tabs只有特定标签页才展示某些按钮 button要用 传递函数引用方式 ()>{} *还有要注意子组件内loading触发 导致的重复渲染

        【干货教程】Windows电脑本地部署运行DeepSeek R1大模型(基于Ollama和Chatbox)

        文章目录 一、环境准备二、安装Ollama2.1 访问Ollama官方网站2.2 下载适用于Windows的安装包2.3 安装Ollama安装包2.4 指定Ollama安装目录2.5 指定Ollama的大模型的存储目录 三、选择DeepSeek R1模型四、下载并运行DeepSeek R1模型五、常见问题解答六、使用Chatbox进行交互6.1 …

        关于YApi接口操作

        YApi有 接口集合 和 测试集合 两个概念。 接口集合 将接口进行分类&#xff0c;使接口结构更清晰&#xff0c;一个接口只能属于一个集合&#xff0c;且不允许与其他接口重名。测试集合 为了方便我们测试接口&#xff0c;测试集合 将若干接口组合在一起&#xff0c;在这里一个接…

        Django REST Framework (DRF) 中用于构建 API 视图类解析

        Django REST Framework (DRF) 提供了丰富的视图类&#xff0c;用于构建 API 视图。这些视图类可以分为以下几类&#xff1a; 1. 基础视图类 这些是 DRF 中最基础的视图类&#xff0c;通常用于实现自定义逻辑。 常用类 APIView&#xff1a; 最基本的视图类&#xff0c;所有其…

        Django简介

        Django是什么 Web应用程序是指在服务器端运行的程序&#xff0c;不需要单独安装&#xff0c;而Django就是其中一个非常流行的框架。 网站运行的主要原理 网站运行的本质就是服务器与客户端之间的数据传输&#xff0c;而其中&#xff0c;超文本传输协议&#xff08;HTTP&…

        JavaScript基础-函数(完整版)

        文章目录 函数基本使用函数提升函数参数arguments对象&#xff08;了解&#xff09;剩余参数(重点)展开运算符(...) 逻辑中断函数参数-默认参数函数返回值-return作用域(scope)全局作用域局部作用域变量的访问原则垃圾回收机制闭包 匿名函数函数表达式立即执行函数 箭头函数箭头…

        1.21作业

        1 unserialize3 当序列化字符串中属性个数大于实际属性个数时&#xff0c;不会执行反序列化 外部如果是unserialize&#xff08;&#xff09;会调用wakeup&#xff08;&#xff09;方法&#xff0c;输出“bad request”——构造url绕过wakeup 类型&#xff1a;public class&…

        LLaMA-Factory|微调大语言模型初探索(3),qlora微调deepseek记录

        前言 上篇文章记录了使用lora微调llama-1b,微调成功,但是微调llama-8b显存爆炸,这次尝试使用qlora来尝试微调参数体量更大的大语言模型,看看64G显存的极限在哪里。 1.Why QLora? QLoRA 在模型加载阶段通过 4-bit 量化大幅减少了模型权重的显存占用。QLoRA 通过 反量化到 …

        TCP传输可靠性保障:理论讲解→实战面试解析

        一、TCP为何需要可靠性保障&#xff1f; TCP作为互联网的"运输队长"&#xff0c;承担着80%以上的网络数据传输任务。其核心使命是&#xff1a;在不可靠的IP层之上&#xff0c;构建端到端的可靠传输通道。 想象一下网购时商品运输需要防丢包、防损坏、防错序&#xff…

        一篇搞懂vue3中如何使用ref、reactive实现响应式数据

        ref 可实现 基本类型、对象类型响应式数据 reactive&#xff1a;只能实现 对象类型响应式 ref实现 基本类型 数据响应式&#xff1a; <template><div class"person"><h2>姓名&#xff1a;{{ name }}</h2><h2>年龄&#xff1a;{{ ag…

        Linux 内核自旋锁spinlock(四)--- queued spinlock

        文章目录 前言一、queued spinlock1.1 简介1.2. spin_lock/spin_unlock 二、源码解析2.1 struct qspinlock2.2 struct qnode2.3 queued_spin_lock2.3.1 快速申请通道CPU0申请锁 2.3.2 慢速申请通道CPU0/1申请锁CPU0/1/2申请锁CPU0/1/2/3申请锁 queued_spin_lock_slowpath总结 2…

        一种最常见的js加密解密

        前言 在前端开发的广袤天地中&#xff0c;你是否遭遇过一些看似“乱码”般的代码&#xff0c;根本无从下手理解&#xff1f;这其实很可能是被 _0x处理过的代码。_0x就像一位神秘的“化妆师”&#xff0c;能把原本清晰的代码改头换面。今天&#xff0c;我就来分享如何破解这些被…

        git使用-克隆远程项目、分支管理

        文章目录 克隆远程项目到本地1. 远程找到需要克隆的项目&#xff0c;复制ssh地址2. idea开启git版本控制&#xff08;如果已经开了&#xff0c;忽略此步骤&#xff09;3. clone远端项目4. 克隆完成 分支管理1. 新建分支2. 切换分支3. 合并分支4. 储存变化 克隆远程项目到本地 …

        Python实战:Excel中文转拼音工具开发教程

        在日常办公中&#xff0c;我们经常需要处理Excel文件&#xff0c;有时候需要将中文转换为拼音缩写以方便检索和使用。今天我将分享一个使用Python开发的小工具&#xff0c;它可以自动将Excel文件中指定列的中文转换为拼音缩写。 C:\pythoncode\new\ConvertExcelcontentToPinyin…