十六、行为型(责任链模式)

责任链模式(Chain of Responsibility Pattern)

概念
责任链模式是一种行为型设计模式,它使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

责任链模式的核心思想是把请求的处理责任从一个对象转移到多个对象上。通过设置链式处理机制,多个对象可以动态参与请求处理,同时提高系统的可扩展性。


应用场景

  1. 多处理器处理请求:当一个请求可能被多个对象处理时,可以采用责任链模式将这些处理对象串联起来,沿着链条传递请求,直到找到合适的处理者。

  2. 避免复杂条件判断:如果在处理某些请求时,需要使用大量的条件语句(if-elseswitch-case),可以通过责任链模式将处理逻辑分散到不同的对象中,从而避免代码臃肿、难以维护。

  3. 日志过滤或权限控制:在日志记录或权限验证的场景中,不同的日志级别或权限控制可以使用责任链模式进行逐级处理。例如,日志系统可以根据不同的日志级别决定是否记录或输出日志信息。

  4. 审批流程:当一个请求需要经过多级审批时,责任链模式可以很好地实现逐级审批的机制。如果某一级不能处理,则传递给下一层。


注意点

  1. 请求必须能最终得到处理:责任链模式的链条中必须有一个对象能够处理请求,否则请求可能被丢失。

  2. 链条过长时可能影响性能:如果链条中包含的处理者对象很多,请求在链中传递的时间可能会较长,因此链的长度不宜过长。

  3. 容易出现不必要的调用:如果链条中的某些处理者不必要地调用了处理方法,可能会导致不必要的性能开销。


核心要素

  1. Handler(处理者接口/抽象类):定义处理请求的接口,同时包含设置下一个处理者的方法。

  2. ConcreteHandler(具体处理者):实现处理者接口的类,负责处理具体的请求,或者将请求传递给下一个处理者。

  3. Client(客户端):向链条上的处理者提交请求,由处理者决定如何处理该请求。


Java代码完整示例

示例:银行审批系统的责任链模式实现

// 抽象处理者
abstract class Approver {
    protected Approver nextApprover;  // 下一个处理者

    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    // 处理请求的抽象方法
    public abstract void approveRequest(int amount);
}

// 具体处理者:经理
class Manager extends Approver {
    @Override
    public void approveRequest(int amount) {
        if (amount <= 1000) {
            System.out.println("Manager approved request of amount " + amount);
        } else if (nextApprover != null) {
            nextApprover.approveRequest(amount);  // 传递给下一个处理者
        }
    }
}

// 具体处理者:总监
class Director extends Approver {
    @Override
    public void approveRequest(int amount) {
        if (amount <= 5000) {
            System.out.println("Director approved request of amount " + amount);
        } else if (nextApprover != null) {
            nextApprover.approveRequest(amount);  // 传递给下一个处理者
        }
    }
}

// 具体处理者:CEO
class CEO extends Approver {
    @Override
    public void approveRequest(int amount) {
        if (amount > 5000) {
            System.out.println("CEO approved request of amount " + amount);
        } else if (nextApprover != null) {
            nextApprover.approveRequest(amount);
        }
    }
}

// 客户端代码
public class ChainOfResponsibilityDemo {
    public static void main(String[] args) {
        Approver manager = new Manager();
        Approver director = new Director();
        Approver ceo = new CEO();

        // 设置责任链:经理 -> 总监 -> CEO
        manager.setNextApprover(director);
        director.setNextApprover(ceo);

        // 提交请求
        System.out.println("Requesting approval for amount 500:");
        manager.approveRequest(500);  // Manager handles this request

        System.out.println("\nRequesting approval for amount 3000:");
        manager.approveRequest(3000);  // Director handles this request

        System.out.println("\nRequesting approval for amount 10000:");
        manager.approveRequest(10000);  // CEO handles this request
    }
}

输出结果

Requesting approval for amount 500:
Manager approved request of amount 500

Requesting approval for amount 3000:
Director approved request of amount 3000

Requesting approval for amount 10000:
CEO approved request of amount 10000

各种变形用法完整示例

  1. 动态责任链

    在某些情况下,责任链的顺序可能并不是固定的。可以动态设置处理者链条,从而灵活地控制请求的传递顺序。

    代码示例:动态责任链

    public class DynamicChainDemo {
        public static void main(String[] args) {
            Approver manager = new Manager();
            Approver director = new Director();
            Approver ceo = new CEO();
    
            // 动态设置责任链
            director.setNextApprover(manager);  // 将总监设置为经理的下一个处理者
            ceo.setNextApprover(director);      // 将CEO设置为总监的下一个处理者
    
            // 提交请求
            System.out.println("Requesting approval for amount 2000:");
            ceo.approveRequest(2000);  // 由于链条是动态的,总监会首先处理
        }
    }
    

    输出结果

    Requesting approval for amount 2000:
    Director approved request of amount 2000
    
  2. 双向责任链

    有时请求可能需要在链条中向前或向后传递。在这种情况下,可以实现双向责任链。

    代码示例:双向责任链

    abstract class BiDirectionalApprover {
        protected BiDirectionalApprover nextApprover;
        protected BiDirectionalApprover prevApprover;
    
        public void setNextApprover(BiDirectionalApprover nextApprover) {
            this.nextApprover = nextApprover;
        }
    
        public void setPrevApprover(BiDirectionalApprover prevApprover) {
            this.prevApprover = prevApprover;
        }
    
        public abstract void approveRequest(int amount);
    }
    
    class ManagerBiDirectional extends BiDirectionalApprover {
        @Override
        public void approveRequest(int amount) {
            if (amount <= 1000) {
                System.out.println("Manager approved request of amount " + amount);
            } else if (nextApprover != null) {
                nextApprover.approveRequest(amount);
            } else if (prevApprover != null) {
                prevApprover.approveRequest(amount);  // 向前传递
            }
        }
    }
    
    // 双向链条示例
    public class BiDirectionalChainDemo {
        public static void main(String[] args) {
            BiDirectionalApprover manager = new ManagerBiDirectional();
            BiDirectionalApprover director = new DirectorBiDirectional();
            BiDirectionalApprover ceo = new CEO();
    
            // 设置链条
            manager.setNextApprover(director);
            director.setPrevApprover(manager);
    
            // 请求
            manager.approveRequest(2000);
        }
    }
    
  3. 链式日志处理

    在日志系统中,可以使用责任链模式实现日志的逐级过滤。例如,只输出大于某个级别的日志。

    代码示例:链式日志处理

    // 抽象日志处理者
    abstract class Logger {
        public static int INFO = 1;
        public static int DEBUG = 2;
        public static int ERROR = 3;
    
        protected int level;
        protected Logger nextLogger;
    
        public void setNextLogger(Logger nextLogger) {
            this.nextLogger = nextLogger;
        }
    
        public void logMessage(int level, String message) {
            if (this.level <= level) {
                write(message);
            }
            if (nextLogger != null) {
                nextLogger.logMessage(level, message);
            }
        }
    
        protected abstract void write(String message);
    }
    
    // 具体日志处理者
    class ConsoleLogger extends Logger {
        public ConsoleLogger(int level) {
            this.level = level;
        }
    
        @Override
        protected void write(String message) {
            System.out.println("Console Logger: " + message);
        }
    }
    
    class FileLogger extends Logger {
        public FileLogger(int level) {
            this.level = level;
        }
    
        @Override
        protected void write(String message) {
            System.out.println("File Logger: " + message);
        }
    }
     // 日志系统示例
    public class LoggerDemo {
        public static void main(String[] args) {
            Logger consoleLogger = new ConsoleLogger(Logger.INFO);
            Logger fileLogger = new FileLogger(Logger.ERROR);
    
            // 设置链条
            consoleLogger.setNextLogger(fileLogger);
    
            consoleLogger.logMessage(Logger.INFO, "This is an information.");
            consoleLogger.logMessage(Logger.ERROR, "This is an error message.");
        }
    }
    

通过这些示例,可以灵活运用责任链模式,根据业务需求构建多种责任链。

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

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

相关文章

洞察前沿趋势!2024深圳国际金融科技大赛——西丽湖金融科技大学生挑战赛技术公开课指南

在当前信息技术与“互联网”深度融合的背景下&#xff0c;金融行业的转型升级是热门话题&#xff0c;创新与发展成为金融科技主旋律。随着区块链技术、人工智能技术、5G通信技术、大数据技术等前沿科技的飞速发展&#xff0c;它们与金融领域的深度融合&#xff0c;正引领着新型…

uniapp:sqlite最详细教程,小白可直接粘贴复制

新建uniapp项目,需要4个页面, loading 启动页:打开数据库,判断数据表是否存在,表内是否有数据,创建数据表的逻辑。 register 注册页:数据表已存在,但是没有数据,需要进入该页面注册第一条数据 index 首页:展示数据列表内的数据,可修改默认,添加新数据 edit 编辑:编…

linux面试题复习

前言 现在只是初版&#xff0c;很多格式我还没有改好&#xff0c;会慢慢修改订正。 可能用到的网址&#xff1a;在线 EXCEL 到 MARKDOWN 转换器。 参考了很多网上的面试题和外网上的面试题&#xff1a; 参考文档&#xff1a; 程序员的50大Linux面试问题及答案 Top 60 Linux …

机床发那科转profinet IO项目案例

目录 1 案例说明 1 2 VFBOX网关工作原理 1 3 准备工作 2 4 网关采集发那科机床数据 2 5 用PROFINET IO协议转发数据 5 6 案例总结 7 1 案例说明 设置网关采集发那科机床数据把采集的数据转成profinet IO协议转发给其他系统。 2 VFBOX网关工作原理 VFBOX网关是协议转换网关&a…

【安当产品应用案例100集】024-BYOE及BYOK在IaaS场景中的应用

在云计算环境中&#xff0c;尤其是涉及到敏感数据时&#xff0c;企业用户可能会选择自带加密工具或密钥&#xff08;即BYOE或BYOK&#xff09;&#xff0c;以确保数据在传输和存储过程中的安全性。这种方式可以防止云服务提供商访问或泄露加密数据&#xff0c;增强数据保护。 …

OpenCV视觉分析之目标跟踪(1)计算密集光流的类DISOpticalFlow的介绍

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 这个类实现了 Dense Inverse Search (DIS) 光流算法。更多关于该算法的细节可以在文献 146中找到。该实现包含了三个预设参数集&#xff0c;以提…

基于Java+Springboot+Vue开发的鲜花商城管理系统

项目简介 该项目是基于JavaSpringbootVue开发的鲜花商城管理系统&#xff08;前后端分离&#xff09;&#xff0c;这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能&#xff0c;同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜…

网络服务请求流程简单理解

网络流程&#xff1a; DNS负责将域名解析为IP地址&#xff0c;ALB可以在多个服务实例之间分配流量&#xff0c;APISIX作为API网关处理更细粒度的流量管理&#xff0c;Service在Kubernetes中为Pod提供稳定的访问入口&#xff0c;而Kubernetes则负责整个应用的部署、扩展和运维。…

基于STM32F103的LED闪烁仿真-定时器中断方式

基于STM32F103的LED闪烁仿真 仿真软件&#xff1a; Proteus 8.17 编程软件&#xff1a; Keil 5 定时器简介&#xff1a; 高级控制定时器(TIM1和TIM8)由一个16位的自动装载计数器组成&#xff0c;它由一个可编程的预分频器驱动。 它适合多种用途&#xff0c;包含测量输入信…

FastGPT学习(2)- 本地开发通过Navicat管理MongoDB、PostgreSQL数据库

1. 背景 前期已经完成FastGPT的本地化部署工作&#xff0c;通过Docker启动FastGPT的相关容器即可运行。&#xff08;共6个容器&#xff09; 2.本地化开发 2.1 前置依赖 2.2 源码拉取 git clone gitgithub.com:labring/FastGPT.git2.3 数据库管理 本地化运行的FastGPT使用…

007、链表的回文结构

0、题目描述 链表回文结构 1、法1 一个复杂的问题可以拆解成几个简单的问题&#xff0c;找中间节点和逆置链表&#xff08;翻转链表&#xff09;之前都做过。 class PalindromeList { public://1、找中间节点ListNode* FindMid(ListNode* A){if (A nullptr || A->next …

博客搭建之路:hexo搜索引擎收录

文章目录 hexo搜索引擎收录以百度为例 hexo搜索引擎收录 hexo版本5.0.2 npm版本6.14.7 next版本7.8.0 写博客的目的肯定不是就只有自己能看到&#xff0c;想让更多的人看到就需要可以让搜索引擎来收录对应的文章。hexo支持生成站点地图sitemap 在hexo下的_config.yml中配置站点…

‘perl‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

‘perl’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。 明明已经根据教程安装了perl环境,但是在cmd中依赖报该错误,本章教程提供解决办法。 一、激活perl环境 state shell ActiveState-Perl-5.36.0此时输入perl -v 是可以直接输出perl版本号的。 二、找到perl的执…

跨域的几种情况和如何解决跨域问题

在网站开发中&#xff0c;经常会遇到跨域问题&#xff0c;下面总结一下集中常见的跨域问题。 1. 不同域名属于跨域&#xff0c;如&#xff1a;www.a.com 和www.b.com&#xff0c;另外www.a.com 和www.a.com.cn也属于不同域名。 2. 主域名和子域名&#xff08;二级域名、三级域…

192×144像素是几寸照片?如何手机拍照制作

在数字摄影时代&#xff0c;像素是衡量照片质量的重要指标之一。那么&#xff0c;192144像素的照片相当于多少英寸呢&#xff1f;又如何使用手机拍摄并制作这样的照片呢&#xff1f;本文将为您解答。 首先&#xff0c;我们需要了解像素和英寸之间的关系。像素是图像的最小单位&…

分布式篇(分布式事务)(持续更新迭代)

一、事务 1. 什么是事务 2. 事务目的 3. 事务的流程 4. 事务四大特性 原子性&#xff08;Atomicity&#xff09; 一致性&#xff08;Consistency&#xff09; 持久性&#xff08;Durability&#xff09; 隔离性&#xff08;Isolation&#xff09; 5. MySQL VS Oracle …

14款被严重低估的安全红队测试工具推荐,网络攻防|网络安全必看的工具合集推荐!

大家好&#xff0c;我是小强 工具往往可以决定网络安全渗透测试或红队演练活动的成败。虽然Kali中的许多工具都已经过验证且稳定可靠&#xff0c;但并不能适合所有渗透测试场景。对于安全红队而言&#xff0c;需要在不同测试需求下&#xff0c;确保有足够的装备来实现测试目标…

洞见数据未来,StarRocks Summit Asia 2024 即将启幕!

在 AI 时代&#xff0c;我们需要怎样的数据基础软件&#xff1f; 数据量和数据类型的需求飞速上涨&#xff0c;我们不仅需要将历史上各种基础设施中的数据进行分析使用&#xff0c;还要关注性能、灵活性、性价比&#xff0c;以及确保单一可信数据源。这一切构成了当前大数据领…

三维管线管网建模工具MagicPipe3D V3.5.3

经纬管网建模系统MagicPipe3D&#xff0c;本地离线参数化构建地下管网三维模型&#xff08;包括管道、接头、附属设施等&#xff09;&#xff0c;输出标准3DTiles、Obj模型等格式&#xff0c;支持Cesium、Unreal、Unity、Osg等引擎加载进行三维可视化、语义查询、专题分析&…

喜报!腾讯云存储获第三届“鼎新杯”优秀案例!

引言 2024年9月24日-25日&#xff0c;由中国通信标准化协会主办、中国信息通信研究院&#xff08;简称“中国信通院”&#xff09;承办、中国通信企业协会支持的“2024数字化转型发展大会”在北京召开。大会公布了第三届“鼎新杯”数字化转型应用大赛案例评选结果。 腾讯云存…