Java描述设计模式(15):责任链模式
本文源码:GitHub·点这里 || GitEE·点这里
一、生活场景描述
1、请假审批流程
公司常见的请假审批流程:请假天数
当 day<=3 天,项目经理审批 当 3<day<=5 天,部门经理审批 当 day>5 天,CEO审批
2、流程图解
3、代码实现
public class C01_InScene { public static void main(String[] args) { // 组装责任链 AuditHandler h1 = new CeoManger(); AuditHandler h2 = new DeptManger(); AuditHandler h3 = new ProjectManger(); h3.setSuccessor(h2); h2.setSuccessor(h1); /* * 测试输出 * 项目经理无权审批 * 部门经理无权审批 * CEO审批:同意【Cicada】,请假【6】天 */ h3.handleLeaveDay("Cicada",6); } } abstract class AuditHandler { //持有下一个处理请求的对象 protected AuditHandler successor = null; public AuditHandler getSuccessor() { return successor; } public void setSuccessor(AuditHandler successor) { this.successor = successor; } public abstract void handleLeaveDay (String user,Integer day); } /** * 项目经理审批 */ class ProjectManger extends AuditHandler{ @Override public void handleLeaveDay(String user, Integer day) { if (day <= 3){ System.out.println("项目经理审批:同意【"+user+"】,请假【"+day+"】天"); } else { System.out.println("项目经理无权审批"); if (getSuccessor() != null){ getSuccessor().handleLeaveDay(user,day); } } } } /** * 部门经理审批 */ class DeptManger extends AuditHandler{ @Override public void handleLeaveDay(String user, Integer day) { if (day > 3 && day <= 5){ System.out.println("部门经理审批:同意【"+user+"】,请假【"+day+"】天"); } else { System.out.println("部门经理无权审批"); if (getSuccessor() != null){ getSuccessor().handleLeaveDay(user,day); } } } } /** * CEO审批 */ class CeoManger extends AuditHandler{ @Override public void handleLeaveDay(String user, Integer day) { if (day > 5){ System.out.println("CEO审批:同意【"+user+"】,请假【"+day+"】天"); } else { if (getSuccessor() != null){ getSuccessor().handleLeaveDay(user,day); } } } }
二、责任链模式
1、基础概念
责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下个的引用而连接起来形成一条链式结构。请求在这个链上传递,直到链上的某一个对象有权处理该请求。请求的客户端不知道链上的哪个对象处理该请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任对象。
2、核心角色
(1)、抽象处理者角色
定义处理请求的接口。接口可以也可以给出一个方法以设定和返回对下个对象引用。这个角色通常由一个Java抽象类或者Java接口实现。
(2)、具体处理者角色
具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下个对象。由于具体处理者持有对下家的引用。
3、模式图解
4、源代码实现
public class C02_Chain { public static void main(String[] args) { // 组装责任链 Handler handler1 = new ConcreteHandler(); Handler handler2 = new ConcreteHandler(); handler1.setHandler(handler2); // 提交请求 handler1.handlerRequest(); } } /** * 抽象处理者角色 */ abstract class Handler { /* * 持有后续的责任对象 */ protected Handler handler; /** * 处理请求的方法 */ public abstract void handlerRequest(); public Handler getHandler() { return handler; } public void setHandler(Handler handler) { this.handler = handler; } } /** * 具体处理者角色 */ class ConcreteHandler extends Handler{ /** * 调用该方法处理请求 */ @Override public void handlerRequest() { /* * 判断是否有后续的责任对象,没有就出来请求,有就直接放过 */ if(getHandler() != null){ System.out.println("放过请求,下个对象处理..."); getHandler().handlerRequest(); } else{ System.out.println("直接处理请求了..."); } } }
三、Spring框架应用
1、DispatcherServlet类的
DispatcherServlet 核心方法 doDispatch。HandlerExecutionChain只是维护HandlerInterceptor的集合,可以向其中注册相应的拦截器,本身不直接处理请求,将请求分配给责任链上注册处理器执行,降低职责链本身与处理逻辑之间的耦合程度。
HandlerExecutionChain mappedHandler = null; mappedHandler = this.getHandler(processedRequest); mappedHandler.applyPreHandle(processedRequest, response); mappedHandler.applyPostHandle(processedRequest, response, mv);
2、HandlerExecutionChain类
这里分析的几个方法,都是从DispatcherServlet类的doDispatch方法中请求的。
- 获取拦截器,执行preHandle方法。
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(request, response, this.handler)) { this.triggerAfterCompletion(request, response, (Exception)null); return false; } } } return true; }
- 在applyPreHandle方法中,执行triggerAfterCompletion方法。
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = this.interceptorIndex; i >= 0; --i) { HandlerInterceptor interceptor = interceptors[i]; try { interceptor.afterCompletion(request, response, this.handler, ex); } catch (Throwable var8) { logger.error("HandlerInterceptor.afterCompletion threw exception", var8); } } } }
- 获取拦截器,执行applyPostHandle方法。
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = interceptors.length - 1; i >= 0; --i) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(request, response, this.handler, mv); } } }
四、模式总结
- 将请求和处理逻辑分开,实现解耦提高系统的灵活性;
- 当责任链过长时,性能会下降,测试也会变得复杂;
- 应用场景:请假、加薪、费用等常见的审批流程;
五、源代码地址
GitHub·地址 https://github.com/cicadasmile/model-arithmetic-parent GitEE·地址 https://gitee.com/cicadasmile/model-arithmetic-parent
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
JAVA描述算法和数据结构(01):稀疏数组和二维数组转换
本文源码:GitHub·点这里 || GitEE·点这里 一、基本简介 1、基础概念 在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。定义非零元素的总数比上矩阵所有元素的总数为矩阵的稠密度。 2、处理方式 1)、记录数组一共有几行几列,有多少个不同的值 2)、把具有不同值的元素的行列及值记录在稀疏数组中,可以缩小程序代码的复杂度。 3、图解描述 稀疏数组表示 [0] 3 4 4 二维数组,3行,4列,4个非0的值; [1] 1 2 2 一行,2列的值是2; [2] 1 3 3 一行,3列的值是3; …以此类推 4、五子棋场景 使用稀疏数组描述 行 列 值 [0] 11 11 2 [1] 1 2 1 [2] 2 3 2 二、代码实现 1、转换流程 二维数组转稀疏数组 1)、遍历二维数组,得到非零元素的个数 2)、创建稀疏数组 3)、二维数组的非零元素写入稀疏数组 稀疏数组转二维数组 1)、读取稀疏数组的首行,创建二维数组 2)、根据稀疏数组描述的有效元素,给二维数组赋值 2、...
- 下一篇
微软与阿里云合作推出“开放应用模型(OAM)”
【大咖・来了 第7期】10月24日晚8点观看《智能导购对话机器人实践》 英文原文:Announcing the Open Application Model (OAM) 原文标题:微软与阿里云合作推出“开放应用模型(OAM)” 用于 Kubernetes 及更多平台的应用开发、运行的开放标准 Kubernetes 已经成为业界领先的容器编排环境,这极大地推动了 Kubernetes 服务在全球各大主要公有云平台上的显著增长。但是,在 Kubernetes 的核心资源中诸如服务、部署等,从整个应用的角度来看,却像是呈现出应用的离散状态。此外,Helm chart 这样的对象,虽然看起来像是可以部署的应用,但真正部署之后,却缺少运行应用所需的应用中心模型。这就需要有一个定义清晰、完整一致的模型,来表达整个应用,而不仅仅是它的模板或者是组件。正是出于这样的考虑,微软与阿里云基于 Open Web 基金会展开合作,推出了开放应用模型(OAM)。 项目地址:https://openappmodel.io,OAM项目目前由规范和实现两部分组成 什么是Open Application Model? ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Hadoop3单机部署,实现最简伪集群
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS6,7,8上安装Nginx,支持https2.0的开启