设计模式教程:责任链模式(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 {
        @Override
        public 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 {
        @Override
        public 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 {
        @Override
        public 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. 禁止未经授权的商业转载。

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

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

        如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

        相关文章

        无人机避障——感知篇(采用Livox-Mid360激光雷达获取点云数据显示)

        电脑配置&#xff1a;Xavier-nx、ubuntu 18.04、ros melodic 激光雷达&#xff1a;Livox_Mid-360 1、安装激光雷达驱动 下载安装Livox-SDK2 如果git clone不了&#xff0c;在github上下载相应的zip进行手动安装&#xff0c;安装网址如下&#xff1a; https://github.com/L…

        ubuntu22.04使用minikube安装k8s

        ubuntu使用minikube安装k8s 准备工作安装步骤安装docker安装kubectl安装minikube导入相关镜像安装相关指令启动minikube服务 安装dashboard组件导入相关镜像创建服务账号安装组件本体验证安装结果 准备工作 下载离线安装包&#xff0c;安装包内容如下&#xff1a; 软件说明ki…

        西门子1200下载、上传程序。

        下载 第一种 直接点击图标下载&#xff0c;此种方式PLC会停机。 第二种 这三种的区别&#xff1a; 上传 创建新的项目。

        基于Openlayers对GeoServer发布的数据进行增删改

        使用GeoServer进行图斑数据管理 本文将介绍如何使用GeoServer进行图斑数据的新增、删除和修改。我们将通过一个Vue.js应用来演示这些功能。 设置Vue.js应用 首先&#xff0c;我们设置Vue.js应用&#xff0c;并添加必要的组件和交互逻辑。 Check.vue Check.vue文件包含初始…

        自动化之ansible(二)

        一、ansible中playbook&#xff08;剧本&#xff09; 官方文档&#xff1a; Ansible playbooks — Ansible Community Documentation 1、playbook的基本结构 一个基本的playbook由以下几个主要部分组成 hosts: 定义要执行任务的主机组或主机。 become: 是否需要使用超级用户…

        函数执行中的栈和寄存器调用

        函数执行中的栈和寄存器调用 函数执行过程中主要用到的寄存器有程序计数器和栈指针。 程序计数器&#xff08;IP&#xff09;&#xff1a;指向下一条执行指令的地址&#xff0c;其值用%rip来表示 栈指针&#xff1a;指向栈顶地址&#xff0c;其值用%rsp来表示 当过程P调用过…

        纯新手教程:用llama.cpp本地部署DeepSeek蒸馏模型

        0. 前言 llama.cpp是一个基于纯C/C实现的高性能大语言模型推理引擎&#xff0c;专为优化本地及云端部署而设计。其核心目标在于通过底层硬件加速和量化技术&#xff0c;实现在多样化硬件平台上的高效推理&#xff0c;同时保持低资源占用与易用性。 最近DeepSeek太火了&#x…

        建筑兔零基础自学python记录22|实战人脸识别项目——视频人脸识别(下)11

        这次我们继续解读代码&#xff0c;我们主要来看下面两个部分&#xff1b; 至于人脸识别成功的要点我们在最后总结~ 具体代码学习&#xff1a; #定义人脸名称 def name():#预学习照片存放位置path M:/python/workspace/PythonProject/face/imagePaths[os.path.join(path,f) f…

        【Java消息队列】应对消息丢失、重复、顺序与积压的全面策略

        应对消息丢失、重复、顺序与积压的全面策略 引言kafka消息丢失生产者消费者重复消费顺序消费消息积压生产者消费者其他RabbitMQ消息丢失生产者事务机制,保证生产者发送消息到 RabbitMQ Server发送方确认机制,保证消息能从交换机路由到指定队列保证消息在 RabbitMQ Server 中的…

        PHP会务会议系统小程序源码

        &#x1f4c5; 会务会议系统 一款基于ThinkPHPUniapp框架&#xff0c;精心雕琢的会议管理微信小程序&#xff0c;专为各类高端会议场景量身打造。它犹如一把开启智慧殿堂的金钥匙&#xff0c;为会议流程优化、开支精细化管理、数量精准控制、标准严格设定以及供应商严格筛选等…

        Unity通过Vosk实现离线语音识别方法

        标注&#xff1a;deepseek直接生成&#xff0c;待验证 在Unity中实现离线语音识别可以通过集成第三方语音识别库来实现。以下是一个使用 Unity 和 Vosk&#xff08;一个开源的离线语音识别库&#xff09;的简单示例。 准备工作 Vosk&#xff1a;一个开源的离线语音识别库&am…

        架构学习第七周--Prometheus

        目录 一、监控系统基础 二、Prometheus介绍 三、Prometheus单机部署 四、服务发现与告警功能 4.1&#xff0c;服务发现 4.2&#xff0c;告警功能实现 五、Prometheus与Kubernetes 5.1&#xff0c;Kubernetes指标 5.2&#xff0c;Prometheus集群部署 一、监控系统基础…

        技术总结 | MySQL面试知识点

        MySQL面试知识点 1.存储引擎1.1 Archive1.2 BlackHole1.3 MyISAM1.4 InnoDB (重点记一下哦)1.5 Memory1.6 CSV 2. 事务2.1. 什么是事务2.2. 事务的特性2.3. 事务的操作sql2.4. 事务的隔离级别 3.三大日志3.1. undo log 回滚日志3.2. redo log 重做日志3.3. bin log 二进制日志4…

        DeepSeek模型快速部署教程-搭建自己的DeepSeek

        前言&#xff1a;在人工智能技术飞速发展的今天&#xff0c;深度学习模型已成为推动各行各业智能化转型的核心驱动力。DeepSeek 作为一款领先的 AI 模型&#xff0c;凭借其高效的性能和灵活的部署方式&#xff0c;受到了广泛关注。无论是自然语言处理、图像识别&#xff0c;还是…

        图论 之 BFS

        文章目录 3243.新增道路查询后的最短距离1311.获取你好友已观看的视频 BFS:广度优先搜索&#xff08;BFS&#xff09; 是一种常用的算法&#xff0c;通常用于解决图或树的遍历问题&#xff0c;尤其是寻找最短路径或层级遍历的场景。BFS 的核心思想是使用队列&#xff08;FIFO 数…

        VSCode集成deepseek使用介绍(Visual Studio Code)

        VSCode集成deepseek使用介绍&#xff08;Visual Studio Code&#xff09; 1. 简介 随着AI辅助编程工具的快速发展&#xff0c;VSCode作为一款轻量级、高度可扩展的代码编辑器&#xff0c;已成为开发者首选的工具之一。DeepSeek作为AI模型&#xff0c;结合Roo Code插件&#x…

        Qt中利用httplib调用https接口

        httplib中如果要调用https接口&#xff0c;需要开启OPENSSL支持&#xff0c;经过半天坑爹得摸索&#xff0c;总结下经验。 1&#xff0c;下载 并安装Win64OpenSSL 地址如下&#xff0c;我Qt版本是5.15.2 &#xff0c;openssl选择的是 64位&#xff08;Win64OpenSSL-3_3_3.msi…

        使用Geotools读取DEM地形数据实战-以湖南省30米数据为例

        目录 前言 一、DEM地形数据介绍 1、DEM数据简介 2、DEM应用领域 3、QGIS中读取DEM数据 二、GeoTools解析地形 1、Maven中依赖引用 2、获取数据基本信息 三、总结 前言 随着全球数字化进程的加速&#xff0c;各类地理空间数据呈爆炸式增长&#xff0c;DEM 数据作为其中的…

        登录-01.基础登录功能

        一.需求分析 当前的页面不需要登录就可以进入&#xff0c;十分不安全&#xff0c;因此要设置登录功能来维护系统的安全性。登录时要根据输入的用户名和密码进行登录校验&#xff0c;如果在数据库中没有找到匹配的用户名和密码的话&#xff0c;那么就无法登录。 因此要先根据用…

        调用click.getchar()时Windows PyCharm无法模拟键盘输入

        文章目录 问题描述解决方案参考文献 问题描述 调用 click.getchar() 时&#xff0c;Windows PyCharm 无法模拟键盘输入 解决方案 Run → Edit Configurations… → Modify options → Emulate terminal in output console 参考文献 Terminal emulator | PyCharm Documentati…