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

news/2025/2/21 18:32:34/

目录

什么是责任链模式

责任链模式的实现

责任链模式角色

责任链模式类图

责任链模式举例

责任链模式代码实现

责任链模式的特点

优点

缺点

使用场景

注意事项

实际应用


什么是责任链模式

        责任链模式(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.ppmy.cn/news/989081.html

相关文章

关于c++中虚函数和虚函数表的创建时机问题

以这段代码为例。 #include <iostream>using namespace std;class Parent { public:Parent(){}virtual void func1() {};virtual void func2() {}; };class Child :public Parent { public:Child():n(0),Parent(){cout << "Child()" << endl;}vir…

pytorch的发展历史,与其他框架的联系

我一直是这样以为的&#xff1a;pytorch的底层实现是c(这一点没有问题&#xff0c;见下边的pytorch结构图),然后这个部分顺理成章的被命名为torch,并提供c接口,我们在python中常用的是带有python接口的&#xff0c;所以被称为pytorch。昨天无意中看到Torch是由lua语言写的&…

2023深圳杯数学建模C题

C题 无人机协同避障航迹规划 平面上A、B两个无人机站分别位于半径为500 m的障碍圆两边直径的延长线上&#xff0c;A站距离圆心1 km&#xff0c;B站距离圆心3.5 km。两架无人机分别从A、B两站同时出发&#xff0c;以恒定速率10 m/s飞向B站和A站执行任务。飞行过程中两架无人机…

【ribbon】Ribbon的使用与原理

负载均衡介绍 负载均衡&#xff08;Load Balance&#xff09;&#xff0c;其含义就是指将负载&#xff08;工作任务&#xff09;进行平衡、分摊到多个操作单元上进行运行&#xff0c;例如FTP服务器、Web服务器、企业核心应用服务器和其它主要任务服务器等&#xff0c;从而协同…

Spring之BeanDefinition(二)

Spring之BeanDefinition 文章目录 Spring之BeanDefinition1、对象和bean的区别2、BeanDefinition作用AutowireCandidate说明Primary说明ConstructorArgumentValues说明第一种使用方式第二种使用方式 MutablePropertyValuesabstract小结 3、BeanDefinition的发展历程3、BeanDefi…

SpringBoot集成Thymeleaf

Spring Boot 集成 Thymeleaf 模板引擎 1、Thymeleaf 介绍 Thymeleaf 是适用于 Web 和独立环境的现代服务器端 Java 模板引擎。 Thymeleaf 的主要目标是为开发工作流程带来优雅的自然模板&#xff0c;既可以在浏览器中正确显示的 HTML&#xff0c;也可以用作静态原型&#xf…

【跨代码仓库合并方案】

1、背景&#xff1a; 1、wiser绑定的uiidA的定制修改内容和ELKO绑定的uiidB基本是一样的&#xff0c;需要手动粘贴同步&#xff0c;增加测试保障风险&#xff0c;还会浪费开发资源投入&#xff1b; 2、施耐德wiser和elko面板两套面板基本一致&#xff0c;但是经过new art升级后…

[NLP]LLaMA与LLamMA2解读

摘要 Meta最近提出了LLaMA(开放和高效的基础语言模型)模型参数包括从7B到65B等多个版本。最值得注意的是&#xff0c;LLaMA-13B的性能优于GPT-3&#xff0c;而体积却小了10倍以上&#xff0c;LLaMA-65B与Chinchilla-70B和PaLM-540B具有竞争性。 一、引言 一般而言&#xff0…