Java二十三种设计模式-责任链模式(17/23)

news2024/11/14 21:23:10

责任链模式:实现请求处理的灵活流转

引言

在这篇博客中,我们深入探讨了责任链模式的精髓,从其定义和用途到实现方法,再到使用场景、优缺点、与其他模式的比较,以及最佳实践和替代方案,旨在指导开发者如何在适当的场景下有效运用这一模式来提高软件设计的灵活性和可维护性。

 基础知识,java设计模式总体来说设计模式分为三大类:

(1)创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

(2)结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

(3)行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

第一部分:责任链模式概述

1.1 定义与用途

责任链模式的基本定义

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许将请求沿着处理者链进行传递,直到某个处理者能够处理该请求为止。

责任链模式是一种行为型设计模式,它通过将请求的发送者和接收者解耦,将这些请求沿着一条链传递,直到链上的某个节点能够处理该请求。这种模式允许系统在运行时动态地添加或修改处理请求的方式,而无需修改已有的代码。

解释为何需要责任链模式

  • 解耦请求者和处理者:责任链模式使得请求的发送者不需要知道具体的处理者是谁,只需要将请求发送到链上即可。
  • 动态处理请求:可以根据需要动态地添加或删除链上的处理者,或者改变它们的处理顺序。
  • 灵活性和可扩展性:当需要支持多种类型的请求或处理方式时,责任链模式提供了一种灵活的解决方案。
  • 简化对象的相互通信:减少了对象之间的直接交互,简化了对象间的关系。

1.2 责任链模式的组成

处理者(Handler)

  • 定义:处理者是一个接口,定义了处理请求的方法和一个指向下一个处理者的引用。
  • 职责:每个具体的处理者需要实现这个接口,并决定是否能够处理接收到的请求。

请求(Request)

  • 定义:请求是传递给处理者的对象,通常包含一些数据和信息,描述了需要被处理的事项。
  • 职责:作为处理者链中传递的信息载体。

上下文(Context)

  • 定义:上下文是请求的起始点,它知道如何创建和维护处理者链。
  • 职责:创建请求并将其传递给链上的首个处理者。

具体处理者(Concrete Handler)

  • 定义:具体处理者实现了处理者接口,具体实现了请求处理的逻辑。
  • 职责:根据请求的类型和内容决定是否处理请求,如果能够处理,则执行相应操作;否则,将请求传递给链上的下一个处理者。

角色之间的交互

  • 请求创建:上下文创建请求并将其传递给链上的第一个处理者。
  • 请求传递:每个处理者检查请求,决定是否能够处理它。如果能够处理,则执行操作;否则,将请求传递给链上的下一个处理者。
  • 请求处理:请求沿着处理者链传递,直到被某个处理者处理。

责任链模式通过将请求的发送者和接收者解耦,提供了一种灵活的方式来处理请求,使得在不修改现有代码的情况下,可以动态地改变请求的处理方式。在下一部分中,我们将通过Java代码示例来展示责任链模式的具体实现。

第二部分:责任链模式的实现

2.1 Java实现示例

以下是使用Java语言实现责任链模式的代码示例。假设我们有一个简单的审批系统,根据不同的审批金额,需要不同级别的经理来批准。

// 处理者接口
interface Approver {
    void setNextApprover(Approver next);
    void approve(PurchaseRequest request);
}

// 具体处理者:主任
class DirectorApprover implements Approver {
    private Approver nextApprover;

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

    @Override
    public void approve(PurchaseRequest request) {
        if (request.getAmount() <= 5000) {
            System.out.println("Director approved: " + request);
        } else {
            if (nextApprover != null) {
                nextApprover.approve(request);
            } else {
                System.out.println("No more approvers in the chain.");
            }
        }
    }
}

// 具体处理者:部门经理
class ManagerApprover implements Approver {
    private Approver nextApprover;

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

    @Override
    public void approve(PurchaseRequest request) {
        if (request.getAmount() <= 10000) {
            System.out.println("Manager approved: " + request);
        } else {
            if (nextApprover != null) {
                nextApprover.approve(request);
            } else {
                System.out.println("No more approvers in the chain.");
            }
        }
    }
}

// 请求类
class PurchaseRequest {
    private double amount;
    private String purpose;

    public PurchaseRequest(double amount, String purpose) {
        this.amount = amount;
        this.purpose = purpose;
    }

    @Override
    public String toString() {
        return "PurchaseRequest{Amount: " + amount + ", Purpose: '" + purpose + "'}";
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Approver managerApprover = new ManagerApprover();
        Approver directorApprover = new DirectorApprover();
        managerApprover.setNextApprover(directorApprover);

        PurchaseRequest request1 = new PurchaseRequest(7000, "Office supplies");
        managerApprover.approve(request1);

        PurchaseRequest request2 = new PurchaseRequest(15000, "Conference equipment");
        managerApprover.approve(request2);
    }
}

2.2 责任链中的角色和职责

处理者(Handler)

  • 职责:定义了一个处理请求的接口,包括设置下一个处理者的方法和处理请求的方法。

请求(Request)

  • 职责:封装了请求的详细信息,可以被处理者链中的任何一个处理者访问和处理。

上下文(Context)

  • 职责:在本示例中,上下文由客户端代码充当,负责创建请求并启动责任链的处理过程。

具体处理者(Concrete Handler)

  • 职责:实现了处理者接口,具体实现了请求处理的逻辑,包括判断请求是否在自己的处理范围内,以及将请求传递给链上的下一个处理者。

相互作用

  • 设置链:客户端代码负责构建责任链,通过setNextApprover方法将各个处理者连接起来。
  • 请求传递:请求从链的开始传递,每个处理者决定是否处理请求或将其传递给下一个处理者。
  • 请求处理:请求最终被能够处理它的处理者处理,或者到达链的末端仍未被处理。

责任链模式通过定义清晰的处理者角色和请求传递机制,实现了请求的动态分发和处理。这种模式在需要灵活处理请求的场景中非常有用,尤其是在请求的处理流程可能变化的情况下。在下一部分中,我们将探讨责任链模式的使用场景。

第三部分:责任链模式的使用场景

3.1 需要灵活处理请求的场景

在软件系统中,经常会遇到需要根据不同的条件以不同方式处理请求的场景。责任链模式通过将请求的发送者和接收者解耦,提供了一种灵活处理请求的方法。

讨论在需要灵活处理请求时,责任链模式的应用:

  • 多样化处理:在不同的处理者中实现不同的业务逻辑,可以根据请求的内容选择不同的处理策略。
  • 易于扩展:当需要添加新的处理方式时,只需添加一个新的处理者类,并将其加入到责任链中,无需修改现有代码。

应用实例:

  • 审批流程:在企业审批流程中,不同的审批级别可能需要不同角色的审批。责任链模式可以灵活地表示这种多级审批流程。
  • 权限验证:在权限验证系统中,可能需要根据不同的用户角色和资源类型进行不同的权限检查。

3.2 请求处理者动态指定的场景

在某些情况下,请求的处理者可能不是预设的,而是根据运行时的条件动态确定的。责任链模式允许在运行时构建处理者链,从而动态地指定请求的处理者。

分析在请求处理者可以动态指定时,责任链模式的优势:

  • 动态构建:可以根据请求的类型或内容动态地构建责任链,使得处理流程更加灵活。
  • 可配置性:通过外部配置或规则引擎来定义责任链的组成和顺序,提高了系统的可配置性。

应用实例:

  • 工作流引擎:在工作流引擎中,任务的处理顺序和处理者可以根据工作流的定义动态确定。
  • 内容管理系统:在内容管理系统中,不同类型或不同优先级的内容可能需要不同的审核流程和审核人员。

责任链模式通过允许请求沿着链传递,直到被适当处理,提供了一种强大的方法来处理请求。这种模式在实际开发中非常有价值,尤其是在需要处理多样化请求或请求处理流程可能变化的情况下。在下一部分中,我们将讨论责任链模式的优点与缺点。

 

第四部分:责任链模式的优点与缺点

4.1 优点

降低耦合度

  • 解耦请求者和处理者:责任链模式使得请求的发送者和接收者之间没有直接的联系,两者通过责任链进行交互,从而降低了耦合度。

提高系统的灵活性

  • 动态调整处理流程:可以在运行时根据需要动态地调整处理流程,如添加、删除或重新排列处理者。

易于扩展

  • 扩展新的处理者:添加新的处理者不需要修改现有代码,符合开闭原则。

简化对象交互

  • 减少直接交互:减少了对象之间的直接交互,简化了对象间的关系。

支持多样化的请求处理

  • 多种处理策略:允许系统支持多种不同的请求处理策略。

4.2 缺点

处理效率问题

  • 性能开销:请求可能需要在多个处理者之间传递,可能会带来性能开销。

请求可能无法被处理

  • 处理者缺失:如果责任链中没有处理者能够处理请求,可能会导致请求被忽略或处理失败。

调试困难

  • 问题定位:在责任链中定位问题可能比较困难,特别是当链比较长或处理逻辑复杂时。

责任链的建立和管理

  • 链的维护:需要管理责任链的建立和维护,确保链的正确性。

可能引起循环引用

  • 循环链:如果不当使用,责任链可能导致循环引用,从而引起无限循环。

责任链模式提供了一种灵活的方式来处理请求,允许请求沿着链传递,直到被适当处理。然而,它也需要谨慎使用,以避免增加系统的复杂性和维护难度。在实际应用中,根据具体需求和场景选择是否使用责任链模式是非常重要的。在下一部分中,我们将比较责任链模式与其他设计模式,并提供一些最佳实践和建议。

 

第五部分:责任链模式与其他模式的比较

5.1 与命令模式的比较

命令模式

  • 定义:命令模式将请求或操作封装为一个对象,允许用户使用不同的请求对客户进行参数化。
  • 特点:命令模式关注于将请求封装成对象,从而允许系统使用不同的请求、队列请求或记录请求。

责任链模式

  • 定义:如前所述,责任链模式通过将请求沿着链传递,直到链上的某个节点能够处理该请求。
  • 特点:责任链模式关注于请求的传递和处理,允许多个对象都有机会处理请求。

对比

  • 请求封装:命令模式强调请求的封装和存储,责任链模式强调请求的传递和处理。
  • 处理方式:命令模式通常由调用者直接执行命令,责任链模式则由多个潜在的处理者依次尝试处理请求。
  • 目的:命令模式用于支持撤销、重做等操作,责任链模式用于实现请求处理的链式传递。

5.2 与中介者模式的对比

中介者模式

  • 定义:中介者模式定义了一个中介对象,用于封装一系列对象之间的交互,从而减少这些对象之间的耦合度。
  • 特点:中介者模式关注于减少对象间的直接交互,通过中介者进行通信。

责任链模式

  • 定义:如前所述,责任链模式允许请求沿着处理者链进行传递,直到被适当处理。

对比

  • 通信方式:中介者模式通过中介者对象来转发请求和响应,责任链模式则通过链式传递请求。
  • 解耦合:中介者模式通过中介者来解耦对象间的直接引用,责任链模式通过分离请求者和处理者来解耦。
  • 灵活性:责任链模式提供了处理请求的灵活性,中介者模式提供了通信方式的灵活性。

责任链模式和命令模式、中介者模式都提供了处理请求的不同方法。每种模式都有其独特的用途和优势,选择使用哪种模式取决于具体的设计需求和场景。在下一部分中,我们将提供责任链模式的最佳实践和建议。

 

第六部分:责任链模式的最佳实践和建议

6.1 最佳实践

确保处理者链的明确终止条件

  • 终止条件:确保责任链有明确的终止条件,防止请求无限循环。

保持处理者职责单一

  • 单一职责原则:每个处理者应该只处理一种类型的请求,保持职责单一。

使用享元模式优化处理者

  • 享元模式:如果处理者之间有共享的资源或状态,可以使用享元模式来优化内存使用。

提供灵活的链构建方式

  • 灵活构建:提供灵活的方式来构建责任链,如通过配置文件或程序逻辑。

确保线程安全

  • 线程安全:在多线程环境中使用责任链模式时,确保处理者是线程安全的。

避免过度复杂的责任链

  • 简化设计:避免构建过于复杂或过长的责任链,以免增加系统的复杂性和降低性能。

6.2 避免滥用

避免在简单场景使用责任链模式

  • 简化解决方案:对于简单的请求处理,使用责任链模式可能过于复杂,应考虑更简单的解决方案。

避免处理者之间的过度耦合

  • 解耦合:保持处理者之间的松耦合,避免它们之间的依赖关系过于紧密。

避免缺乏明确的终止条件

  • 明确终止:确保责任链有明确的终止条件,防止请求处理过程中的不确定性。

6.3 替代方案

使用状态模式

  • 状态变化:当对象的状态变化需要改变其行为时,可以考虑使用状态模式。

使用策略模式

  • 算法替换:如果需要根据不同的条件执行不同的算法或行为,策略模式可能是一个更好的选择。

使用命令模式

  • 命令封装:对于需要将请求或操作封装为对象的场景,命令模式可以提供帮助。

使用中介者模式

  • 减少耦合:当系统中对象之间的通信过于复杂时,中介者模式可以减少对象间的直接耦合。

责任链模式提供了一种灵活的方式来处理请求,允许请求沿着处理者链进行传递,直到被适当处理。然而,合理使用责任链模式并避免其缺点是至关重要的。了解其替代方案可以帮助开发者根据具体需求和场景选择最合适的设计模式。在实际开发中,应根据具体情况灵活运用责任链模式,以达到最佳的设计效果。

结语

责任链模式提供了一种强大的方法来处理请求,允许请求沿着处理者链进行传递,直到被适当处理。通过本文的深入分析,希望读者能够对责任链模式有更全面的理解,并在实际开发中做出合理的设计选择。

博主还写了其他Java设计模式关联文章,请各位大佬批评指正:

(一)创建型模式(5种):

Java二十三种设计模式-单例模式(1/23)

Java二十三种设计模式-工厂方法模式(2/23)

Java二十三种设计模式-抽象工厂模式(3/23)

Java二十三种设计模式-建造者模式(4/23)

Java二十三种设计模式-原型模式(5/23)

(二)结构型模式(7种): 

Java二十三种设计模式-适配器模式(6/23)

Java二十三种设计模式-装饰器模式(7/23)

Java二十三种设计模式-代理模式(8/23)

Java二十三种设计模式-外观模式(9/23)

Java二十三种设计模式-桥接模式(10/23)

Java二十三种设计模式-组合模式(11/23)

Java二十三种设计模式-享元模式(12/23)

 (三)行为型模式(11种): 

Java二十三种设计模式-策略模式(13/23)

Java二十三种设计模式-模板方法模式(14/23)

Java二十三种设计模式-观察者模式(15/23)

Java二十三种设计模式-迭代子模式(16/23)

持续更新中......敬请关注 

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

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

相关文章

力扣第 411 场周赛题解

3258. 统计满足 K 约束的子字符串数量 I 给你一个 二进制 字符串 s 和一个整数 k。 如果一个 二进制字符串 满足以下任一条件&#xff0c;则认为该字符串满足 k 约束&#xff1a; 字符串中 0 的数量最多为 k。字符串中 1 的数量最多为 k。 返回一个整数&#xff0c;表示 s …

系统编程-进程初步1

5 进程初步 一、认识进程 -- 进程Process是指计算机中已运行的程序&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;是操作系统结构的基础 -- 程序运行起来就是一个进程 进程存在于运行内存中程序存在于硬盘中 -- windows下查看进程使用任务管理器进行查看 1…

EXCEL——Vlookup17个高级用法

大纲 一、基本语法 1、参数详解 二、入门篇 1、单条件查找 2、屏蔽查找返回的错误值 三、进阶篇 1、反向查找 2、包含查找 3、区间查找 4、含通配符查找 5、多列查找 6、多区域查找 四、高级篇 1、多条件查找 2、合并单元格查找 3、带合并单元格的多条件查找 …

轻松玩转音频剪辑:推荐四大必备工具!

在这个多媒体时代&#xff0c;音频剪辑技能变得至关重要。无论是制作短视频、音频节目&#xff0c;还是音乐创作&#xff0c;一款得心应手的音频剪辑工具都能让你事半功倍。今天&#xff0c;我们将推荐几款热门音频剪辑工具&#xff0c;助你轻松玩转声音世界 福昕音频剪辑 链…

【数学建模】趣味数学模型——等额还款数学模型

问题 在银行贷款中&#xff0c;通常采用等额还款。假定银行贷款的年利率为 p&#xff0c;贷款 k 元&#xff0c;分 m 年采用每月等额还款方式还清。问每月还款多少钱&#xff1f;总共还的钱是多少&#xff1f;每月还款中还本金和利息各是多少元&#xff1f; 如果考虑每月等额…

Webrtc之SDP协议

SDP简介 SDP 最常用于 RTC 实时通话的协商过程&#xff0c;在 WebRTC 中&#xff0c;通信双方在连接阶段使用 SDP 来协商后续传输过程中使用的音视频编解码器(codec)、主机候选地址、网络传输协议等。 在实际的应用过程中&#xff0c;通信双方可以使用 HTTP、WebSocket、Data…

MySQL数据库主从复制

主从复制原理 MySQL的复制类型 基于语句的复制 &#xff08;默认&#xff09;基于行的复制混合类型的复制MySQL主从复制的工作过程 主从复制设置 主从复制时基于二进制文件的所以需要打开二进制文件 主数据库 在MySQL配置文件/etc/my.cnf修改或增加 #启用了MySQL的二进制日…

集合及数据结构第三节————包装类和简单认识泛型

系列文章目录 集合及数据结构第三节————包装类和简单认识泛型 包装类和简单认识泛型 基本数据类型和对应的包装类装箱和拆箱泛型泛型类的使用裸类型(Raw Type) &#xff08;了解&#xff09;泛型如何编译的泛型的上界泛型方法 文章目录 系列文章目录集合及数据结构第三节…

linux上常见问题

1.普通用户下&#xff0c;不能使用sudo 解决方法 1.切换到root用户下执行该指令是没有问题的 2.更改配置文件sudoers 1.进入root用户下&#xff1a;su - 2.编辑sudoers :visudo 此时就打开了一个文件 3.在该文件找到这么一行内容&#xff1a;root ALL(ALL) ALL 4.在该行的…

CUDA-MODE课程笔记 第8课: CUDA性能检查清单

我的课程笔记&#xff0c;欢迎关注&#xff1a;https://github.com/BBuf/how-to-optim-algorithm-in-cuda/tree/master/cuda-mode CUDA-MODE课程笔记 第8课: CUDA性能检查清单 课程笔记 这节课实际上算是CUDA-MODE 课程笔记 第一课: 如何在 PyTorch 中 profile CUDA kernels 这…

(16)prometheus(普罗米修斯)监控的搭建

prometheus是由go语言编写的&#xff0c;监控服务器是否正常运行的工具&#xff0c;使用experter工具收集数据&#xff0c;传到prometheus服务器。可以结合grafana图形化和pagerduty报警发送有邮件和信息。 实验环境&#xff1a; 关掉防火墙和selinux grafana.example.com 1…

为什么CNAPP将会是网络安全领域的一场革命?

随着越来越多的组织开始业务上云&#xff0c;云原生应用保护变得越来越复杂。众多高度碎片化产品&#xff0c;很难去保护一个广泛的、动态变化的攻击场景。当前想要解决这一难题&#xff0c;有一个很好的思路&#xff0c;就是云原生应用保护平台&#xff08;CNAPP&#xff09;。…

第二届机器人与软件工程前沿国际会议在贵阳闭幕

2024年8月13日&#xff0c;第二届机器人与软件工程前沿国际会议&#xff08;FRSE 2024&#xff09;在贵阳圆满闭幕。 本次大会由长沙理工大学主办&#xff0c;贵州大学、湖南科技大学、爱迩思出版社&#xff08;ELSP&#xff09;&#xff0c;ESBK国际学术交流中心、AC学术平台…

Python 办公自动化 处理 Excel 数据 【1】推荐

话说学好办公自动化,走遍天下都不怕&#xff01;&#xff01;&#xff01; 好的&#xff0c;现在开始。 因为是一些办公自动化的应用场景&#xff0c;所以需要电脑支持excel、word和ppt以及python的运行环境。 如果有电脑不支持Excel word ppt的以及python环境下载安装配置可…

Spring 声明式事务 @Transactional

目录 一、添加依赖 二、Transactional 作用 三、Transactional详解 3.1 rollbackFor 3.2 事务隔离级别 3.3 Spring 事务传播机制 Spring 声明式事务 Transactional的使用很简单&#xff0c;只需要添加依赖&#xff0c;在需要的方法或者类上添加 Transactional注解即可。 …

珠海盈致联手深圳盈怡成功上线“混工单柔性智能生产装备”

珠海盈致联手深圳盈怡推出的“混工单柔性智能生产装备”在全面而严密的市场测试中显示出卓越的性能和极高的用户满意度。 经过两年的精细研发和内部测试优化&#xff0c;该柔性生产线已成功完成了样板工厂的所有环节&#xff0c;在深圳市贤丰科技有限公司成功试跑上线&#xf…

联影医疗笔试考什么?如何通过联影在线测评|附真题库面试攻略

职小豚 一、联影医疗公司介绍 嘿&#xff0c;朋友们&#xff01;今天咱们来聊聊联影医疗这家在医疗领域大放异彩的企业。 联影医疗&#xff0c;那可是医疗科技界的一颗璀璨明星&#xff01;它就像一位勇敢的探索者&#xff0c;在医疗影像设备的研发和创新道路上不断前行。 联…

机器视觉运动控制一体机VPLC532E在汽车胶带缠绕的开放式CNC应用

市场应用背景 在汽车线束和零配件中&#xff0c;胶带缠绕是一种常见且重要的加工工艺&#xff0c;主要用于线束/零配件的捆扎、固定、绝缘保护等应用。在缠绕头控制下&#xff0c;胶带均匀缠绕在汽车线束/零配件表面&#xff0c;完成缠绕后&#xff0c;系统自动执行切割。汽车…

(普通用户)Cannot connect to the Docker daemon at unix:///var/run/docker.sock.

报错&#xff1a; Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?#大概像以下的报错内容 MernyPierreMBP:~ merny24$ docker info Client:Version: 26.1.4Context: defaultDebug Mode: falseServer: ERROR: Cann…

可以给IP地址申请SSL证书实现HTTPS访问吗?

IP地址证书&#xff0c;全称为IP地址的SSL/TLS证书&#xff0c;是一种专为公网IP地址&#xff08;或内网映射的外网&#xff09;颁发的数字证书。这种证书由受信任的证书颁发机构&#xff08;CA&#xff09;签发&#xff0c;旨在确保通过该IP地址进行的通信&#xff08;特别是H…