在上一节的拦截器中提到,程序的设计者一般会用拦截器替替代动态代理,将动态代理的逻辑隐藏起来,而把拦截器接口提供给开发者,使开发者不需要关系动态代理的具体实现过程,但是有时候需要多个拦截器,而且拦截器之间会相互依赖,比如我们从公司的OA上提交一个请假单的时候,这个请假单会经过直接主管、部门经理、人力资源的层层审核,在请假被批准之前会被各级部门领导进行拦截,而且人力的审核依赖部门经理的审核结果,部门经理的审核又依赖直接主管的审核结果,这里的直接主管、部门经理和人力资源就像是三个拦截器,请假单这个对象在这一条拦截器链上进行传递,由此可以抽象地得出责任链模式的定义:

当一个对象在一条链上被多个拦截器拦截处理(拦截器也可以不处理)时,我们把这样的设计模式称为责任链模式,它用于一个对象在多个角色中传递的场景。---以上定义摘自《互联网轻量级框架整合开发》。

下面以员工请假为例,在请假单审核通过之前,需要被直接主管、部门经理和HR审核,这里面传递的对象是请假单,拦截器是三个领导。

第一步:创建审核请假单的拦截器接口

 /*
* 定义一个审核请假单的拦截器接口
*/
public interface ExamineLeaveInteceptor {
//审批之前检查上一流程是否走完
public boolean before(Object proxy,Object target,Method method,Object[] args); //如果上一个拦截器未处理完,则当前拦截器不予处理
public void around(Object proxy,Object target,Method method,Object[] args); //审批之后签名
public void after(Object proxy,Object target,Method method,Object[] args);
}

第二步:创建三个拦截器类,实现上面定义的接口

 /*
* 定义一个直接主管审核拦截器,实现审核请假单接口
*/
public class DirectorExamineInterceptor implements ExamineLeaveInteceptor {
public boolean before(Object proxy, Object target, Method method, Object[] args) {
boolean result = true;
System.out.println("主管同意之前检查信息是否填写完整");
return result;
} public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.println("打回重新填写"); } public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("审核完毕,主管签名");
}
} /*
* 部门经理审核拦截器
*/
public class ManagerExamineInterceptor implements ExamineLeaveInteceptor { public boolean before(Object proxy, Object target, Method method, Object[] args) {
boolean result = true;
System.out.println("部门经理审核之前检查是否通过员工主管审核");
return result;
} public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.println("员工主管没通过,部门经理不予审核"); } public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("审核完毕,经理签名");
} } *
* hr审核拦截器
*/
public class HrExamineInterceptor implements ExamineLeaveInteceptor { public boolean before(Object proxy, Object target, Method method, Object[] args) {
boolean result = true;
System.out.println("hr审核之前检查部门经理是否通过");
return result;
} public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.println("部门经理没通过,hr不予审核"); } public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("审核完毕,hr签名");
} }

第三步:创建请假单类

 /*
* 请假单类
*/
public class LeaveFile {
public String name; //请假单名称
public String userName; //请假人
public int leavel; //请假类型 public LeaveFile(String name, String userName, int leavel) {
this.name = name;
this.userName = userName;
this.leavel = leavel;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public int getLeavel() {
return leavel;
} public void setLeavel(int leavel) {
this.leavel = leavel;
}
}

第四步:创建审核请假单接口及实现类

 /*
* 审核请假单接口
*/
public interface ExamineLeaveInterface { public void examine(LeaveFile file);
} /*
* 审核请假单实现类
*/
public class ExamineLeaveInterfaceImpl implements ExamineLeaveInterface {
/**
* file:请假单
*/
public void examine(LeaveFile file) {
System.out.println("员工" + file.getUserName() + "的请假单审核完毕");
}
}

第五步:创建动态代理类,代理真是对象方法

 /*
* 动态代理类,代理拦截器方法
*/
public class DynamicProxyInterceptor implements InvocationHandler {
private Object target;// 真实对象
private String interceptorName;// 拦截器全限定名 public DynamicProxyInterceptor(Object target, String interceptorName) {
this.target = target;
this.interceptorName = interceptorName;
} // 返回代理对象
public static Object bind(Object target, String interceptorName) {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
new DynamicProxyInterceptor(target, interceptorName));
} // 动态生成拦截器,并执行方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (interceptorName == null) {
return method.invoke(target, args);
} Object result = null;
ExamineLeaveInteceptor examineInterceptor = (ExamineLeaveInteceptor) Class.forName(interceptorName)
.newInstance();
// 如果拦截器中的before方法执行成功,则执行真实对象的方法,否则不能通过
if (examineInterceptor.before(proxy, target, method, args)) {
result = method.invoke(target, args);
examineInterceptor.after(proxy, target, method, args);
} else {
examineInterceptor.around(proxy, target, method, args);
}
return result;
} }

第六步:申请请假

 /*
* 用户提交请假单
*/
public class AskForLeave {
public static void main(String[] args) {
LeaveFile file = new LeaveFile("请假单", "张三", 0);
//获取直接主管动态代理对象
ExamineLeaveInterface directProxy = (ExamineLeaveInterface) DynamicProxyInterceptor.bind(new ExamineLeaveInterfaceImpl(),"com.daily.dutychain.DirectorExamineInterceptor");
//获取部门经理动态代理对象,依赖直接主管
ExamineLeaveInterface managerProxy = (ExamineLeaveInterface) DynamicProxyInterceptor.bind(directProxy,"com.daily.dutychain.ManagerExamineInterceptor");
//获取人力资源动态代理对象,依赖部门经理
ExamineLeaveInterface hrProxy = (ExamineLeaveInterface) DynamicProxyInterceptor.bind(managerProxy,"com.daily.dutychain.HrExamineInterceptor");
hrProxy.examine(file); }
}

第七步:查看执行结果

 hr审核之前检查部门经理是否通过
部门经理审核之前检查是否通过员工主管审核
主管同意之前检查信息是否填写完整
员工张三的请假单审核完毕
审核完毕,主管签名
审核完毕,经理签名
审核完毕,hr签名

从结果可以看到,一个请假单需要经过不同层级的审核,最终才能通过,这就是责任链模式,每个拦截器负责自身人物的同时又要依赖上一级拦截器的处理结果。

Java内功修炼系列一责任链模式的更多相关文章

  1. Java设计模式(14)责任链模式(Chain of Responsibility模式)

    Chain of Responsibility定义:Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合, ...

  2. java设计模式解析(11) Chain责任链模式

    设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析(4) ...

  3. Java设计模式系列之责任链模式

    责任链模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道 ...

  4. 浅谈Java五大设计原则之责任链模式

    首先我们得先定义一个责任链模式: 责任链模式是一种线性执行流程,多个对象都有机会去执行同一个任务,只是在执行过程中, 由于执行的权利和范围不一样,那么当自己不能处理此任务时,就必须将这个任务抛给下一个 ...

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

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

  6. Java描述设计模式(15):责任链模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景描述 1.请假审批流程 公司常见的请假审批流程:请假天数 当 day<=3 天,项目经理审批 当 3<day<= ...

  7. Java设计模式(九)责任链模式 命令模式

    (十七)责任链模式 责任链模式的目的是通过给予多个对象处理请求的机会,已解除请求发送者与接受者之间的耦合关系.面对对象的开发力求对象之前保持松散耦合,确保对象各自的责任最小化.这种设计能够使得系统更加 ...

  8. Java内功修炼系列一代理模式

    代理模式是JAVA设计模式之一,网上设计模式相关的博文铺天盖地,参考它们有助于自己理解,但是所谓“尽信书不如无书”,在参考的同时也要思考其正确性,写博客也是为了记录自己理解知识点的思路历程和心路历程, ...

  9. Java内功修炼系列一工厂模式

    工厂模式是一种创建型模式,它提供了一种新的创建对象的方式,一般情况下我们都习惯用new关键字直接创建对象.有时候会遇到这种情况,我们需要根据具体的场景选择创建什么类型的对象,可能有多种类型都能选择,但 ...

随机推荐

  1. 运用shtml类型文件,实现项目页面的分割。

    学过动态网页,如asp.php的人知道如何去引用网站头部.底部文件包含.例如在php中有一个方法:include();这个方法能在当前文档中引入外部文件,从而方便网站的开发和维护,然而html静态文件 ...

  2. .net core, docker 在vs2019开发过程中的问题以及解决办法

    .net core, docker 在vs2019开发过程中的问题以及解决办法 记录下来,帮助Ta人~ 1.vs调试,快Build完后提示Docker 端口:xxxx,xxxx,xxxx占用 解决办法 ...

  3. UVA 511 Do You Know the Way to San Jose?

    题目链接:https://vjudge.net/problem/UVA-511 题目翻译摘自<算法禁赛入门经典> 题目大意 有 n 张地图(已知名称和某两个对角线端点的坐标)和 m 个地名 ...

  4. 如何将指定文件或文件夹直接提交到svn指定目录?

    如何将指定文件或文件夹直接提交到svn指定目录? 一般我们都是按以下步骤操作的: 1.先将那个目录checkout下来 2.将要添加的文件或者文件夹放到这个目录中 3.右击文件执行svn菜单中的add ...

  5. 手把手教你 GitLab 的安装及使用(转)

    深山田 关注 2018.01.30 22:58 字数 1696 阅读 15559评论 2喜欢 15 前言 新入职公司,发现公司还在使用落后生产工具 svn,由于重度使用过 svn 和 git ,知道这 ...

  6. Resource Archiver HDU - 3247 AC自动机+BFS+状压

    题意: 给出n个资源串,m个病毒串,现在要如何连接资源串使得不含病毒串(可以重叠,样例就是重叠的). 题解: 这题的套路和之前的很不同了,之前的AC自动机+DP的题目一般都是通过teir图去转移, 这 ...

  7. Redis理解和使用

    摘抄并用于自查笔记 1. Redis简介 我们日常Java Web开发,一般使用数据库进行存储,在数据量较大的情况下,单一使用数据库保存数据的系统会因为面向磁盘,磁盘读写速度比较慢而存在严重的性能弊端 ...

  8. Python中死锁的形成示例及死锁情况的防止

    死锁示例搞多线程的经常会遇到死锁的问题,学习操作系统的时候会讲到死锁相关的东西,我们用Python直观的演示一下.死锁的一个原因是互斥锁.假设银行系统中,用户a试图转账100块给用户b,与此同时用户b ...

  9. windows安装apache系统中无apache2服务解决方案

    一直都是用WIN开发PHP,今天有用户反映SHUGUANG CMS在APACHE+PHP中不能正常运行,只好自己机器配置个环境测试(http://xz.8682222.com)遇到点小问题,搜索相关资 ...

  10. 介绍一下再Apache下的Tomcat负载均衡的一些使用问题

    在负载均衡技术中,硬件设备是比较昂贵的,对于负载均衡的学习者如果不是在企业中应用或者是学员中学习,很少有机会能碰到实际操作的训练.(http://xz.8682222.com)所以,很多朋友都会选择软 ...