03-JAVA设计模式-责任链模式

责任链模式

什么是责任链模式

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,允许你将请求沿着处理者链进行传递。每个处理者均对请求进行某些处理,并可决定是否将请求沿着链传递下去。这种模式给予请求的处理者更加灵活的组织结构。

在Java中实现责任链模式,通常需要定义一个处理者接口,该接口包含一个或多个方法用于处理请求和决定是否传递请求。
然后,创建具体的处理者类,实现这个接口。 每个处理者可以持有对下一个处理者的引用,从而形成处理者链。

  • 优点

    • 降低了耦合度: 责任链模式通过将请求的处理逻辑分散到多个处理对象中,减少了请求发送者与多个请求处理者之间的耦合。请求发送者只需要将请求发送到链的头部,而不需要知道链的具体结构或处理逻辑。
    • 增强了系统的可扩展性: 当需要增加新的处理逻辑时,只需要创建一个新的处理对象并将其添加到链中即可,无需修改现有代码。这使得系统的扩展变得更加容易和灵活。
    • 提高了系统的灵活性: 每个处理对象都可以独立地决定是否处理请求,以及是否将请求传递给下一个处理对象。这种灵活性使得系统可以根据不同的场景和需求进行动态调整。
    • 实现了请求的有序处理: 通过合理地安排处理对象在链中的顺序,可以确保请求按照特定的顺序进行处理。这对于某些需要按照特定顺序执行的操作非常有用。
  • 缺点

    • 可能导致性能问题: 由于请求需要在多个处理对象之间进行传递,因此可能会增加系统的处理时间。特别是在处理链较长或处理逻辑较复杂的情况下,性能问题可能会更加明显。
    • 调试难度较大: 当责任链较长且处理逻辑复杂时,调试可能会变得相对困难。因为请求在多个处理对象之间传递,定位问题的来源可能需要跨越多个类和方法。
    • 可能导致请求丢失: 如果没有正确设置处理对象的下一个引用,或者处理对象在处理请求时出现了异常,可能会导致请求在链中丢失,从而无法得到处理。
    • 可能增加代码的复杂性: 为了实现责任链模式,需要编写多个处理对象的代码,并确保它们之间的正确连接和传递。这可能会增加代码的复杂性,特别是在处理逻辑较为复杂的情况下。

开发中常见场景

  • java中,异常机制就是一种责任链模式
  • Servlet开发中,过滤器的链式处理
  • Struts2中,拦截器的调用也是典型的责任链模式

案例

公司里,请假条的审批流程:

  • 请假天数小于3天,主任审批
  • 请假天数大于3天,小于10天,经理审批
  • 请假天数大于10天,小于30天,总经理审批
  • 请假天数大于30天,提示拒绝

UML

在这里插入图片描述

  • 定义请假单,包含请假人,请假天数,请假原因属性
  • 定义一个处理者接口,并提供两个接口:
    • 自己的处理方式
    • 设置下一处理者
  • 定义主任、经理,总经理三个处理者,定义一个属性存储下一处理者引用,自己处理方式接口中,根据需求进行判断处理,否则调用下一处理者进行处理

实现代码

LeaveOrder.java

// 请假单
public class LeaveOrder {// 请假人private String name;// 请假天数private int days;// 原因private String reason;public LeaveOrder(String name, int days, String reason) {this.name = name;this.days = days;this.reason = reason;}public String getName() {return name;}public int getDays() {return days;}public String getReason() {return reason;}
}

LeaveHandle.java

// 定义处理者接口
public interface LeaveHandle {// 定义本人处理方式接口void handleRequest(LeaveOrder leaveOrder);// 定义下一处理者的引用void setNextHandle(LeaveHandle leaveHandle);
}

DirectorLeaveHandle.java

// 主任
public class DirectorLeaveHandle implements LeaveHandle{// 定义一个属性 用于持有下一处理者private LeaveHandle nextHandler;@Overridepublic void handleRequest(LeaveOrder leaveOrder) {if(leaveOrder != null && leaveOrder.getDays() <= 3 && leaveOrder.getDays() > 0){System.out.printf("主任审批-允许请假-请假人:%s-请假天数:%s-理由:%s%n",leaveOrder.getName(),leaveOrder.getDays(),leaveOrder.getReason());}else {// 通过持有引用 调用下已处理者进行处理nextHandler.handleRequest(leaveOrder);}}@Overridepublic void setNextHandle(LeaveHandle leaveHandle) {this.nextHandler = leaveHandle;}
}

ManagerLeaveHandle.java

// 经理
public class ManagerLeaveHandle implements LeaveHandle{// 定义一个属性 用于持有下一处理者private LeaveHandle nextHandler;@Overridepublic void handleRequest(LeaveOrder leaveOrder) {if(leaveOrder != null && leaveOrder.getDays() <= 10 && leaveOrder.getDays() > 3){System.out.printf("经理审批-允许请假-请假人:%s-请假天数:%s-理由:%s%n",leaveOrder.getName(),leaveOrder.getDays(),leaveOrder.getReason());}else {// 通过持有引用 调用下已处理者进行处理nextHandler.handleRequest(leaveOrder);}}@Overridepublic void setNextHandle(LeaveHandle leaveHandle) {this.nextHandler = leaveHandle;}
}

GeneralManagerLeaveHandle.java

// 总经理
public class GeneralManagerLeaveHandle implements LeaveHandle{// 定义一个属性 用于持有下一处理者private LeaveHandle nextHandler;@Overridepublic void handleRequest(LeaveOrder leaveOrder) {if(leaveOrder != null && leaveOrder.getDays() <= 30 && leaveOrder.getDays() > 10){System.out.printf("总经理审批-允许请假-请假人:%s-请假天数:%s-理由:%s%n",leaveOrder.getName(),leaveOrder.getDays(),leaveOrder.getReason());}else {System.out.println("超过30天拒绝请假");}}@Overridepublic void setNextHandle(LeaveHandle leaveHandle) {this.nextHandler = leaveHandle;}
}

TestClient.java

public class TestClient {public static void main(String[] args) {// 创建请假单LeaveOrder order = new LeaveOrder("张三",15,"回家"); 创建处理人// 主任DirectorLeaveHandle directorLeaveHandle = new DirectorLeaveHandle();// 经理ManagerLeaveHandle managerLeaveHandle = new ManagerLeaveHandle();// 总经理GeneralManagerLeaveHandle generalManagerLeaveHandle = new GeneralManagerLeaveHandle();// 设置责任链directorLeaveHandle.setNextHandle(managerLeaveHandle);directorLeaveHandle.setNextHandle(generalManagerLeaveHandle);// 提交请假申请directorLeaveHandle.handleRequest(order);}
}

执行结果:

在这里插入图片描述

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git

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

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

相关文章

Windows版Apache5.7解压直用(免安装-绿色-项目打包直接使用)

windows下Apache分类 Apache分为 安装版和解压版 安装版: 安装方便&#xff0c;下一步------下一步就OK了&#xff0c;但重装系统更换环境又要重新来一遍&#xff0c;会特别麻烦 解压版&#xff08;推荐&#xff09;&#xff1a; 这种方式&#xff08;项目打包特别方便&#…

String类中常见面试题

1.string类属于基本类型吗&#xff1f; string类不是基本类型&#xff1b;它属于引用数据类型 2.操作字符串的类有哪些?有什么区别&#xff1f; 有三种&#xff1a;string,stringBuilder,stringBuffer 区别&#xff1a; String:不可变类&#xff0c;字符串一旦被创建就不能…

给你的AppImage创建桌面快捷方式

原文链接 https://www.cnblogs.com/HGNET/p/16396589.html 运行环境:Ubuntu 22.04 LTS 1.首先准备好AppImage文件并放在一个你知道的地方 2.打开终端&#xff0c;在/usr/share/applications下新建APP.desktop文件&#xff08;APP可以改成你的应用名称&#xff09; cd /usr/s…

【C++算法竞赛 · 图论】图的存储

前言 图的存储 邻接矩阵 方法 复杂度 应用 例题 题解 邻接表 方法 复杂度 应用 前言 上一篇文章中&#xff08;【C算法竞赛 图论】图论基础&#xff09;&#xff0c;介绍了图论相关的概念和一种图的存储的方法&#xff0c;这篇文章将会介绍剩下的两种方法&#xff…

Sonatype Nexus 服务器迁移

因为服务器的升级和调整&#xff0c;有时候会对安装 Sonatype Nexus 的服务器进行迁移到新服务器上。 从技术架构上来说&#xff0c;Sonatype Nexus 我们使用的是 AWS 的存储&#xff0c;所以我们并不需要拷贝大量的数据。 文件夹结构 在备份和恢复之前&#xff0c;我们需要…

【C++】为什么需要CMake?

文章目录 Cmake是什么&#xff1f;Cmake是怎么出现的&#xff1f;C语言为什么会有头文件&#xff1f;C程序的编译流程C程序编译演化史 Cmake是什么&#xff1f; 很多C小白刚进入公司开始接触业务代码的时候&#xff0c;或者在学校实验室接触一些大型的C项目的时候&#xff0c;…

MATLAB 自定义实现点云法向量和曲率计算(详细解读)(64)

MATLAB 自定义实现点云法向量和曲率计算(详细解读)(64) 一、算法介绍二、算法步骤三、算法实现1.代码 (完整,注释清晰,可直接用)2.结果一、算法介绍 首先说明: ------这里代码手动实现,不调用matlab提供的法向量计算接口,更有助于大家了解法向量和曲率的计算方法,…

H2O-3机器学习平台源码编译的各种坑

H2O-3机器学习平台是一个非常适合非专业人士学习机器学习的平台&#xff0c;自带WebUI&#xff0c;效果还是蛮不错的&#xff0c;官方也提供了jar包&#xff0c;一条命令就能直接运行&#xff0c;非常方便&#xff0c;但最近有源码编译的需求&#xff0c;实际操作过程中&#x…

基于8B/10BGT收发器的PHY层设计(1)

一、PHY层简介 PHY层&#xff08;Physical Layer&#xff09;是OSI模型中最低的一层&#xff0c;也是最基本的一层&#xff0c;PHY是物理接口收发器&#xff0c;它实现物理层。包括MII/GMII&#xff08;介质独立接口&#xff09;子层、PCS&#xff08;物理编码子层&#xff09…

ARM内核的CPU架构模型

1.引言 程序员在编码的时候&#xff0c;如果想有进一步的提升&#xff0c;我认为还是要深入底层理解程序运行原理才好。最近看了一些ARM架构的讲解&#xff0c;总结了如下。虽然是以ARM为原型画的图形&#xff0c;但是对于C和C的编程&#xff0c;还是有一些参考价值的。 2. AR…

Java 基于微信小程序的智能停车场管理小程序

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Nexus 如何修改启动端口

默认的 Nexus 的启动端口为 8081。 如果我们使用这个启动端口可能会对我们其他的服务有冲突。 我们需要使用 Nexus 的默认启动端口。 修改文件 根据我们的安装配置为&#xff1a; /opt/nexusdata/nexus3/etc 目录下的 nexus.properties 文件。 注释掉 Jetty 的配置中有关端…