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

【设计模式精解】Java实现责任链模式(职责链模式)优雅处理多级请求(概述,使用场景,优缺点,代码示例)

目录

责任链模式是什么?

责任链模式优缺点?

责任链模式应用场景?

举例证明责任链模式

不用责任链模式的朴素写法

责任链模式重构

结构图

代码

哪些源码里用过责任链模式?


责任链模式是什么?

责任链设计模式是一种行为型设计模式,其主要目的是解耦请求发送者和请求接收者,让多个对象都有机会处理请求。

在责任链模式中,多个处理器依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条,链条上的每个处理器各自承担各自的处理职责。

责任链模式优缺点?

优点在于,它可以动态地添加、删除和调整处理者对象,从而灵活地构建处理链。同时,它也避免了请求发送者和接收者之间的紧耦合。
责任链模式也有一定的缺点,例如如果处理链过长或者处理时间过长,可能会对系统性能产生一定的影响。

责任链模式应用场景?

责任链模式常用于请求的预处理、请求的过滤等场景。例如,可以使用责任链模式来实现前置校验、日志记录等功能。

举例证明责任链模式

例子:小菜想要加薪,需要先向经理申请,如果经理没权利,就向总监上报,总监也没权限,向总经理上报。

不用责任链模式的朴素写法

// 申请
public class Request {private String requestType;private String requestContent;private int number;public String getRequestType() {return requestType;}public void setRequestType(String requestType) {this.requestType = requestType;}public String getRequestContent() {return requestContent;}public void setRequestContent(String requestContent) {this.requestContent = requestContent;}public int getNumber() {return number;}public void setNumber(int number) {this.number = number;}
}// 管理者
public class Manager {private String name;public Manager(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void handleRequest(String managerLevel, Request request) {if (managerLevel.equals("经理")) {if (request.getRequestType().equals("请假")) {System.out.println("员工" + request.getRequestContent() + "请假" + request.getNumber() + "天");System.out.println("审批人" + this.name);} else if (request.getRequestType().equals("加薪")) {System.out.println("经理无权处理");}} else if (managerLevel.equals("总监")) {if (request.getRequestType().equals("请假")) {System.out.println("员工" + request.getRequestContent() + "请假" + request.getNumber() + "天");System.out.println("审批人" + this.name);} else if (request.getRequestType().equals("加薪")) {System.out.println("总监无权处理");}} else if (managerLevel.equals("总经理")) {if (request.getRequestType().equals("请假")) {System.out.println("员工" + request.getRequestContent() + "请假" + request.getNumber() + "天");System.out.println("审批人" + this.name);} else if (request.getRequestType().equals("加薪") && request.getNumber() <= 500) {System.out.println("员工" + request.getRequestContent() + "请求" + request.getNumber() + "元加薪");System.out.println("审批人" + this.name);} else if (request.getRequestType().equals("加薪") && request.getNumber() > 500) {System.out.println("再说吧!");}}}
}

客户端程序

public class Client {public static void main(String[] args) {Manager jingli = new Manager("经理");Manager zongjian = new Manager("总监");Manager zongjingli = new Manager("总经理");Request request = new Request();request.setRequestType("加薪");request.setRequestContent("小菜请求加薪");request.setNumber(500);jingli.handleRequest("经理", request);zongjian.handleRequest("总监", request);zongjingli.handleRequest("总经理", request);System.out.println("-------------------------------------------------------");// 请假request.setRequestType("请假");request.setRequestContent("小菜请求请假");request.setNumber(5);jingli.handleRequest("经理", request);zongjian.handleRequest("总监", request);zongjingli.handleRequest("总经理", request);}
}

测试结果

可以看到,上面的代码,类有太多的责任,违背了单一职责原则,增加新的管理类别,需要修改这个类,违背开闭原则,所以我们需要用责任链模式去重构它

责任链模式重构

UML结构图

代码

// 处理者
public abstract class Handler {private Handler nextHandler;private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public Handler getNextHandler() {return nextHandler;}public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public Handler(String name) {this.name = name;}public abstract void handleRequest(Request request);
}// 经理处理器
public class JingliHandler extends Handler {public JingliHandler(String name) {super(name);}@Overridepublic void handleRequest(Request request) {if (request.getRequestType().equals("请假")) {System.out.println("员工" + request.getRequestContent() + "请假" + request.getNumber() + "天");System.out.println("审批人" + this.getName());} else if (request.getRequestType().equals("加薪")) {System.out.println("员工" + request.getRequestContent() + request.getNumber() + "元加薪");System.out.println(this.getName() + "无权处理,交给上级");this.getNextHandler().handleRequest(request);}}
}// 总监处理器
public class ZongjianHandler extends Handler{public ZongjianHandler(String name) {super(name);}@Overridepublic void handleRequest(Request request) {if (request.getRequestType().equals("请假")) {System.out.println("审批人" + this.getName());} else if (request.getRequestType().equals("加薪")) {System.out.println(this.getName() + "无权处理,交给上级");this.getNextHandler().handleRequest(request);}}
}// 总经理处理器
public class ZongjingliHandler extends Handler{public ZongjingliHandler(String name) {super(name);}@Overridepublic void handleRequest(Request request) {if (request.getRequestType().equals("请假")) {System.out.println("审批人" + this.getName());} else if (request.getRequestType().equals("加薪") && request.getNumber() <= 500) {System.out.println("审批人" + this.getName());} else if (request.getRequestType().equals("加薪") && request.getNumber() > 500) {System.out.println("再说吧!!");}}
}

客户端程序

public class Client {public static void main(String[] args) {JingliHandler jingli = new JingliHandler("经理");ZongjianHandler zongjian = new ZongjianHandler("总监");ZongjingliHandler zongjingli = new ZongjingliHandler("总经理");jingli.setNextHandler(zongjian);zongjian.setNextHandler(zongjingli);Request request = new Request();request.setRequestType("加薪");request.setRequestContent("小菜请求加薪");request.setNumber(500);jingli.handleRequest(request);System.out.println("-------------------------------------------------------");// 请假request.setRequestType("请假");request.setRequestContent("小菜请求请假");request.setNumber(5);jingli.handleRequest(request);}
}

测试结果

image.png

如果经理可以处理的话,直接返回,如果不可以,就交给上级去处理。

哪些源码里用过责任链模式?

之前在看 Mybatis 3.4.x 源码时了解到 Interceptor 底层实现就是责任链模式。
开门见山,直接把视线聚焦到 Mybatis 源码,版本号 3.4.7-SNAPSHOT。

和我们上面用到的责任链模式差不太多,有处理器集合 interceptors,有添加处理器方法。

Mybatis 查询 SQL 的分页语句就是使用 Interceptor 实现,比如市场上的 PageHelper、Mybatis-Plus 分页插件再或者我们自实现的分页插件。

拿查询语句举例,如果定义了多个查询相关的拦截器,会先经过拦截器的代码加工,所有的拦截器执行完毕后才会走真正查询数据库操作。

如果我的内容对你有帮助,请辛苦动动您的手指为我点赞,评论,收藏。感谢大家!

http://www.dtcms.com/a/327369.html

相关文章:

  • Rust:构造函数 new() 如何进行错误处理?
  • 信号(Signal)** 是一种进程间异步通信机制,用于通知进程发生发生了某种事件(如错误、用户中断等)
  • 疯狂星期四文案网第37天运营日记
  • Apache POI中通过WorkBook写入图片后出现导出PDF文件时在不同页重复写入该图片问题,如何在通过sheet获取绘图对象清除该图片
  • 通过限制对象的内存分配位置来实现特定的设计目标
  • 【数据结构入门】堆
  • powerbi本地报表发布到web,以得到分享链接
  • C99中的变长数组(VLA)
  • 什么是 Spring MVC?
  • 中扬立库与西门子深化技术协同 共绘智能仓储创新蓝图
  • clean install 和 clean package 的区别
  • JVM学习笔记-----图解方法执行流程
  • 百胜软件×华为云联合赋能,“超级国民品牌”海澜之家新零售加速前行
  • 【力扣494】目标和
  • 【软考中级网络工程师】知识点之 IP QoS 技术
  • JVM宝典
  • 面试八股之从Java到JVM层面深入解析ReentrantLock实现原理
  • 力扣top100(day01-05)--矩阵
  • 开放原子开源生态大会:麒麟信安加入openEuler社区AI联合工作组,聚焦操作系统开源实践与行业赋能
  • Linux下的软件编程——文件IO
  • Openlayers基础教程|从前端框架到GIS开发系列课程(24)openlayers结合canva绘制矩形绘制线
  • 循环神经网络
  • THCV215一种高速视频数据收发器,采用低电压差分信号(LVDS)技术支持高速串行数据传输,支持1080p/60Hz高分辨率传输
  • 【[特殊字符][特殊字符] 协变与逆变:用“动物收容所”讲清楚 PHP 类型的“灵活继承”】
  • Gradle(二)Gradle的优势、项目结构介绍
  • 电商双11美妆数据分析(一)
  • Honeywell霍尼韦尔A205压力传感器HC41H106P060169419G固瑞克117764美国制造
  • Rust 项目编译故障排查:从 ‘onnxruntime‘ 链接失败到 ‘#![feature]‘ 工具链不兼容错误
  • KAQG:一种用于生成难度可控问题的知识图谱的增强的RAG系统(论文大白话)
  • 2025AI行业升级生态战:谁在“种树”?谁在“造林”?