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

news/2024/10/19 6:16:55/

责任链模式

什么是责任链模式

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

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

  • 优点

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

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

开发中常见场景

案例

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

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

UML

在这里插入图片描述

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

实现代码

LeaveOrder.java

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

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

DirectorLeaveHandle.java

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

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

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

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.ppmy.cn/news/1425530.html

相关文章

第22天:安全开发-PHP应用留言板功能超全局变量数据库操作第三方插件引用

第二十二天 一、PHP留言板前后端功能实现 开发环境&#xff1a; DW PHPStorm PhpStudy Navicat Premium DW : HTML&JS&CSS开发 PHPStorm : 专业PHP开发IDE PhpStudy &#xff1a;Apache MYSQL环境 Navicat Premium: 全能数据库管理工具 二、数据库创建&架…

线程互斥补全和加锁原理

上篇博客&#xff0c;我们用互斥锁完成了互斥的功能。 #include<iostream> #include<thread> #include<unistd.h> #include<functional> #include<vector> using namespace std; template<class T> using func_tfunction<void(T)>…

使用Docker部署开源建站工具—Halo,并实现个人博客公网访问

目录 推荐 前言 1. Docker部署Halo 1.1 检查Docker版本 如果未安装Docker可参考&#xff1a; 已安装Docker步骤&#xff1a; 1.2 在Docker中部署Halo 2. Linux安装Cpolar 2.1 打开服务器防火墙 2.2 安装cpolar内网穿透 3. 配置Halo个人博客公网地址 4. 固定Halo公网…

微信小程序开发五(与springboot整合)

首先在微信开发者工具中开启不校验合法域名&#xff0c;这个才能本地访问 实现一个小功能&#xff1a; 展示数据信息&#xff0c;每条数据的颜色不一样 后端&#xff1a;springbootmybatisplusmysql 依赖&#xff1a; <dependency><groupId>com.baomidou</grou…

前端近7天,近半个月,近1个月,近1年的日期处理

前端如何获取近7天,近1年的日期进行查询? methods:{//近7天getRangeDate(ranges) {let nowDays new Date();let getYear nowDays.getFullYear();let getMonth nowDays.getMonth() 1;let getDate nowDays.getDate();let nd new Date();nd nd.valueOf();nd nd - ranges…

ceph介绍

一、前言 Ceph 是一个完全分布式的系统&#xff0c;它将数据分布在整个集群中的多个节点上&#xff0c;以实现高可用性和容错性&#xff0c;ceph支持对象存储、块存储、文件存储所以被称为统一存储&#xff0c;ceph的架构由以下组件组成:mon、mgr、osd、mds、cephfs、rgw&#…

豆瓣影评信息爬取 (爬虫)

代码块&#xff1a; from lxml import etree import requestsheaders{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0 }url_list[] for i in range(0,5):i*20urlsf"https:…

学习BOM

目录 前言: 1. BOM组成&#xff1a; 1.1Window 对象&#xff1a; 1.1Location 对象&#xff1a; 1.2Navigator 对象&#xff1a; 1.2.1 navigator 对象包含了关于浏览器的信息包括&#xff1a; 1.3History 对象&#xff1a; 1.4常用的history的方法和属性: 1.4Document…