当前位置: 首页 > news >正文

设计模式行为型——责任链模式

目录

什么是责任链模式

责任链模式的实现

责任链模式角色

责任链模式类图

责任链模式举例

责任链模式代码实现

责任链模式的特点

优点

缺点

使用场景

注意事项

实际应用


什么是责任链模式

        责任链模式(Chain of Responsibility Pattern)又叫职责链模式是一种行为型设计模式,它通过建立一个对象链来依次处理请求,将请求的发送者和接收者解耦,并允许多个对象都有机会处理请求。其目的是为了解决请求端与实现端的解耦。其实现过程类似递归调用。责任链模式的核心是定义责任链节点的接口以及节点之间的关系,它允许动态的增加和修改责任链中的节点。

责任链模式的实现

责任链模式角色

抽象处理者(Handler):定义了处理请求的接口,并维护一个指向下一处理者的引用。通常包含一个处理方法 handleRequest()。
具体处理者(ConcreteHandler):实现了抽象处理者接口,对请求进行具体处理,如果自身无法处理,则将请求转发给下一处理者。

责任链模式类图

 

责任链模式举例

        以公司采购审批为例,不同金额的采购需要不同人员的审批,比如20000以下需要项目经理审批,20000-50000需要部门经理审批,50000以上需要总经理审批。此时我们把审批流程可以看作一个审批责任链条,进而可以使用责任链模式。

责任链模式代码实现

实体请求类

package com.common.demo.pattern.chain;import java.math.BigDecimal;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 实体请求类* @date 2023/07/27 13:35:41*/
public class PurchaseReq {/*** 请求类型*/private int type;/*** 金额*/private BigDecimal price;/*** 用途*/private String purpose;public PurchaseReq(int type, BigDecimal price, String purpose) {this.type = type;this.price = price;this.purpose = purpose;}public int getType() {return type;}public void setType(int type) {this.type = type;}public BigDecimal getPrice() {return price;}public void setPrice(BigDecimal price) {this.price = price;}public String getPurpose() {return purpose;}public void setPurpose(String purpose) {this.purpose = purpose;}@Overridepublic String toString() {return "PurchaseReq{" +"type=" + type +", price=" + price +", purpose=" + purpose +'}';}
}

抽象处理者角色

package com.common.demo.pattern.chain;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 抽象审批者处理类, 抽象处理者角色* @date 2023/07/27 13:44:42*/
public abstract class Approver {Approver approver;String name;public Approver() {}public Approver(String name) {this.name = name;}/*** 下一个处理者*/public void setApprover(Approver approver) {this.approver = approver;}/*** 处理审批请求的方法,得到一个请求,处理是子类实现*/public abstract void process(PurchaseReq purchaseReq);}

具体处理者角色

package com.common.demo.pattern.chain;import java.math.BigDecimal;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 项目经理 具体审批者* @date 2023/07/27 13:49:16*/
public class ProjectManager extends Approver {public ProjectManager(String name) {super(name);}@Overridepublic void process(PurchaseReq purchaseReq) {// 小于 5000 项目经理审批即可if (purchaseReq.getPrice().compareTo(new BigDecimal(5000)) == -1) {System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,审批终结!");} else {System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,进入下一级审批!");approver.process(purchaseReq);}}
}
package com.common.demo.pattern.chain;import java.math.BigDecimal;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 部门经理 具体审批者* @date 2023/07/27 13:49:48*/
public class DepartmentManager extends Approver{public DepartmentManager(String name) {super(name);}@Overridepublic void process(PurchaseReq purchaseReq) {// 小于 20000 大于 5000, 部门经理审批即可if(purchaseReq.getPrice().compareTo(new BigDecimal(20000))==-1){System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,审批终结!");} else {System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,进入下一级审批!");approver.process(purchaseReq);}}
}
package com.common.demo.pattern.chain;import java.math.BigDecimal;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 总经理 具体审批者* @date 2023/07/27 13:50:45*/
public class GeneralManager extends Approver {public GeneralManager(String name) {super(name);}@Overridepublic void process(PurchaseReq purchaseReq) {// 大于 20000 ,总经理审批if (new BigDecimal(20000).compareTo(purchaseReq.getPrice()) == -1) {System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,审批终结!");} else {System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,进入下一级审批!");approver.process(purchaseReq);}}
}

测试类

package com.common.demo.pattern.chain;import java.math.BigDecimal;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 测试类* @date 2023/07/27 14:23:01*/
public class Test {public static void main(String[] args) {PurchaseReq purchaseRequest1 = new PurchaseReq(1, new BigDecimal(1000), "购买饮水机");PurchaseReq purchaseRequest2 = new PurchaseReq(2, new BigDecimal(6000), "购买打印机");PurchaseReq purchaseRequest3 = new PurchaseReq(2, new BigDecimal(30000), "购买苹果笔记本办公");ProjectManager projectManager = new ProjectManager("项目经理");DepartmentManager departmentManager = new DepartmentManager("部门经理");GeneralManager generalManager = new GeneralManager("总经理");//设置下一级处理人projectManager.setApprover(departmentManager);departmentManager.setApprover(generalManager);//都从项目经理开始处理projectManager.process(purchaseRequest1);projectManager.process(purchaseRequest2);projectManager.process(purchaseRequest3);}
}

测试截图

责任链模式的特点

优点

  1. 降低耦合度:将请求和处理分开,请求的发送者和接收者各个组件间完全解耦。
  2. 简化了对象:使得对象不需知道链的结构,请求者无需知道接受者,无需知道其如何处理。
  3. 增强灵活性:通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任对象。 
  4. 新增便捷性:增加新的请求处理类很方便。

缺点

  1. 因为只关心自己内部实现,不关心链内部结构,开发调试会比较麻烦。不容易确认调用的哪一个实现。
  2. 增加系统的资源消耗。因为链式调用,可能会进行很多次判断,因为每个实现都会判断是否能够处理该请求,不能处理则调用下一个,增加了系统开销。
  3. 不能保证请求被消化,因其特殊特性,在处理之前会判断是否能够处理,如果每一个链都不能处理,那么该请求无法被消化。

使用场景

  1. 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
  2. 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 
  3. 可动态指定一组对象处理请求。

注意事项

  1. 合理设计责任链的节点:责任链模式的核心是将任务分解为一系列的处理节点,每个节点都有机会处理任务或将其传递给下一个节点。在设计责任链节点时,需要根据实际情况合理地划分节点责任,确保每个节点的功能清晰、独立、可扩展,并且能够按需组合形成不同的责任链。
  2. 灵活配置责任链:责任链模式支持动态配置责任链,也就是可以在运行时通过添加、移除或修改节点来构建不同的责任链。这种灵活性可以根据实际需求动态调整责任链的结构和顺序,但也需要注意避免责任链过长、过于复杂,以及节点的重叠或缺失等问题。
  3. 节点的执行顺序:责任链模式中,每个节点都有机会处理任务,但处理的顺序是非常重要的。在设计责任链时,需要仔细考虑节点的执行顺序,确保任务能够按照预期的流程依次经过每个节点,同时避免出现死循环或执行顺序混乱等问题。
  4. 避免责任链的滥用:责任链模式可以很好地解耦请求发送者和接收者之间的关系,但也容易被滥用。在应用责任链模式时,需要审慎选择,确保责任链模式能够带来真正的价值,而不是增加复杂性或降低代码可维护性。
  5. 错误处理机制:在责任链模式中,如果没有合适的节点处理任务,任务可能会无法得到处理或处理结果不符合预期。因此,在设计责任链时,需要考虑错误处理机制,例如设置默认处理节点、定义异常处理策略等,以确保任务能够得到妥善处理,并且在发生异常时能够及时进行处理和反馈。

实际应用

  1. Spring框架中的拦截器:拦截器是Spring框架中的一种常见组件,它可以在请求处理前后进行一些额外的处理,例如身份验证、日志记录、权限控制等。拦截器就是利用了责任链模式来将多个处理对象构成一条拦截器链,然后逐个处理请求。Spring框架提供了很多拦截器,例如HandlerInterceptor、WebRequestInterceptor等。
  2. Servlet中的过滤器:Servlet中的过滤器也是一种常见的使用责任链模式的场景。过滤器可以在请求处理前后进行一些额外的处理,例如安全认证、数据预处理、异常处理等。
  3. Java 8中的Lambda表达式:Java 8中的Lambda表达式可以看作是一种函数式接口,它利用责任链模式来组合、封装和传递函数对象。Lambda表达式可以通过链式结构形成一个函数的序列,然后按顺序逐个执行这些函数并返回结果,从而可以在Java中实现函数式编程。
  4. Netty中的处理器Pipeline:Netty是一种基于事件驱动的网络通信框架,它利用责任链模式和事件监听机制来处理请求。Netty中的处理器Pipeline是一条处理请求的链,该链中的每个处理器都可以对请求进行处理和传递,从而形成一个完整的事件处理流程。

更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)

http://www.lryc.cn/news/105985.html

相关文章:

  • Xamarin.Android中Intent的使用
  • matplotlib绘制方波圆周分解动画
  • vue3+ts 实现枚举
  • 【Python】5分钟了解11个最佳的Python编译器和解释器
  • 如何安装、部署、启动Jenkins
  • sqlalchemy flask长时间未使用 导致数据库连接失效
  • Ubuntu 20.04 系统或图像界面卡死或完全无响应处理方法
  • Linux编辑器 - vim使用
  • 【Windows】磁盘快捷修复
  • Java 线程的多种状态
  • AI绘画| 迪士尼风格|可爱头像【附Midjourney提示词】
  • 【浪费了我两个小时时间】Microsoft store无法加载页面0x80131500
  • 【动态规划】子序列系列
  • URL存储解锁数据管理的新思路,重新定义数据传输与共享(@vue/repl)
  • matlab程序中文乱码
  • 【计算机视觉|语音分离】期望在嘈杂环境中聆听:一个用于语音分离的不依赖于讲话者的“音频-视觉模型”
  • curl 介绍和使用
  • 5、VMWARE安装、MobaXterm SSH连接 、Ubuntu xrdp安装使用
  • Docker dockerfile 案例:centos 支持 vim
  • Git忽略已经提交过一次的文件 Git忽略文件
  • Scala项目找不到或无法加载主类
  • 八大排序算法--选择排序(动图理解)
  • 6.s081(Fall 2022)Lab2: system calls
  • SAMBA 文件分享相关 笔记
  • Mr. Cappuccino的第53杯咖啡——Mybatis源码分析
  • 修改文件格式(查看文件拓展名)
  • 利用鸿鹄可观测性监控Istio Ingress网关
  • vscode 前端开发插件 2023
  • 使用docker部署Wordpress
  • 7.31黄金最新行情走势分析及多空交易策略