本文源码: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);
}
}
}

四、模式总结

  1. 将请求和处理逻辑分开,实现解耦提高系统的灵活性;
  2. 当责任链过长时,性能会下降,测试也会变得复杂;
  3. 应用场景:请假、加薪、费用等常见的审批流程;

五、源代码地址

GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent

Java描述设计模式(15):责任链模式的更多相关文章

  1. Java常见设计模式之责任链模式

    原文地址:  http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html 在阎宏博士的<JAVA与模式>一书中开 ...

  2. 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)

    原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of R ...

  3. php设计模式之责任链模式

    php设计模式之责任链模式 实际问题 你的论坛有举报功能,版主能解决粗口方面的举报,警察能解决严重一点的黄赌毒方面的举报,更严重的反政府的举报就需要由国安局来完成. 职场中每个人都有直属的上级,如果到 ...

  4. python设计模式之责任链模式

    python设计模式之责任链模式 开发一个应用时,多数时候我们都能预先知道哪个方法能处理某个特定请求.然而,情况并非总是如此.例如,想想任意一种广播计算机网络,例如最早的以太网实现.在广播计算机网络中 ...

  5. 设计模式之责任链模式——Java语言描述

    责任链模式为请求创建了一个接受者对象的链.这种模式给予请求的类型,对请求的发送者和接受者进行解耦.这种类型的设计模式属于行为模式.在这种模式下,通常每个接收者都包含对另一个接收者的引用.如果一个对象不 ...

  6. 详解java设计模式之责任链模式

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt175 从击鼓传花谈起 击鼓传花是一种热闹而又紧张的饮酒游戏.在酒宴上宾客依次 ...

  7. JAVA设计模式之责任链模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其 ...

  8. Java进阶篇设计模式之八 ----- 责任链模式和命令模式

    前言 在上一篇中我们学习了结构型模式的享元模式和代理模式.本篇则来学习下行为型模式的两个模式, 责任链模式(Chain of Responsibility Pattern)和命令模式(Command ...

  9. Java设计模式应用——责任链模式

    生产一个产品,需要依次执行多个步骤,才能完成,那么是使用责任链模式则是极好的. 在性能告警模块开发过程中,创建一条告警规则需要执行阈值解析,中间表生成,流任务生成,规则入库,告警事件入库等诸多操作.如 ...

随机推荐

  1. 反射,Expression Tree,IL Emit 属性操作对比

    .net的反射(Reflection) 是.Net中获取运行时类型信息的一种方法,通过反射编码的方式可以获得 程序集,模块,类型,元数据等信息. 反射的优点在于微软提供的API调用简单,使用方便: 表 ...

  2. 解决python -m pip install --upgrade pip 升级不成功问题

    1.使用命令出现. You are , however version is available. You should consider upgrading via the 'python -m p ...

  3. rabbitmqctl: Error unable to connect to node 'rabbit@xxxxx' nodedown

    RabbitMQ使用rabbitmqctl add_user的时候报以下错误: Creating user "xxxx" ... Error: unable to connect ...

  4. 松软科技课堂:sql函数-AVG

    定义和用法 AVG 函数返回数值列的平均值.NULL 值不包括在计算中. SQL AVG() 语法 SELECT AVG(column_name) FROM table_name SQL AVG() ...

  5. 50 (OC)* URL Scheme 网页地址协议

    在Xcode 9 下,新建的工程,在plist文件中注册URL Schemes,从safari无法打开问题 1:URL Scheme是什么 2:URL Scheme有什么作用 3:URL Scheme ...

  6. 什么是App推广技术?

    在移动互联网红利消失殆尽.市场竞争日趋激烈的背景下,App的推广越来越难了,如何去有效的进行推广,吸引更多的用户流量,成为了众多互联网企业最为关注的问题. 而App 推广技术指的就是通过一些技术的方式 ...

  7. Python连载39-生成器、next函数、yield返回值

    ​一.生成器 1.定义(generator):一边循环一边计算下一个元素的机制/算法 2.满三个条件 (1)每次调用都能产生出for循环需要的下一个元素 (2)如果达到最后一个后,能够爆出StopIt ...

  8. 主动降噪技术(ANC)的前生今世--概念历史

    一 概念 假如使用一句通俗的语言来概述ANC的原理的话,那就是:通过发出与噪声相位相反,频率.振幅相同的声波与噪声干涉实现相位抵消. 使用比较正式的语言来解释就是:动降噪通过降噪系统产生与外界噪音相等 ...

  9. npm install 时间很长解决方案

    国外镜像站很慢,所以我们可以更换为国内的镜像站 首先可以get命令查看registry npm congfig get registry 如果你没有变更果regustry你的结果应该会是这样的 也就是 ...

  10. [python]汉诺塔问题

    相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏.该游戏是在一块铜板装置上,有三根杆(编号A.B.C),在A杆自下而上.由大到小按顺序放置64个金盘(如下图).游戏的目标:把A杆上的金盘全部 ...