在上一节的拦截器中提到,程序的设计者一般会用拦截器替替代动态代理,将动态代理的逻辑隐藏起来,而把拦截器接口提供给开发者,使开发者不需要关系动态代理的具体实现过程,但是有时候需要多个拦截器,而且拦截器之间会相互依赖,比如我们从公司的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. 尚学linux课程---4、linux网络配置及linux文件

    尚学linux课程---4.linux网络配置及linux文件 一.总结 一句话总结: linux下的etc目录是配置文件的目录,所以很多的文件配置操作都可以看到它的身影:比如 init系列命名,比如 ...

  2. 16.ajax_case07

    # 通过搜索接口抓取etherscan上的合约地址 # https://etherscan.io/ import requests import re header = { 'Accept': 'te ...

  3. 7_1.springboot2.x启动配置原理_1.创建SpringApplication对象

    环境准备 springboot2.1.9.idea2019. pom.xml 解析 几个重要的事件回调机制 配置在META-INF/spring.factories ApplicationContex ...

  4. USACO 2008 November Gold Cheering up the Cows /// MST oj24381

    题目大意: 输入n,p:n个点,p条路 接下来n行输入c[]:在各个点需要花费的时间 接下来p行输入u,v,w:u点到v点的路需要花费时间w 求经过所有点且最后回到起点的最少花费时间 https:// ...

  5. [WPF自定义控件]?Window(窗体)的UI元素及行为

    原文:[WPF自定义控件]?Window(窗体)的UI元素及行为 1. 前言 本来打算写一篇<自定义Window>的文章,但写着写着发觉内容太多,所以还是把使用WindowChrome自定 ...

  6. 2019-11-7-C#-dotnet-线程不安全的弱引用缓存

    title author date CreateTime categories C# dotnet 线程不安全的弱引用缓存 lindexi 2019-11-7 9:45:5 +0800 2019-11 ...

  7. Pthread spinlock自旋锁

    锁机制(lock) 是多线程编程中最常用的同步机制,用来对多线程间共享的临界区(Critical Section) 进行保护. Pthreads提供了多种锁机制,常见的有:1) Mutex(互斥量): ...

  8. 理清Java中try-catch-finally带return的执行顺序

    前言:try-catch-finally带return和异常时,它们之间执行顺序问题是留下来的一个小疑问,今天搞清楚它们 第一种情况:无异常 //1.try-catch-finally都带有retur ...

  9. ros Python找不到msg包的问题解决办法

    https://answers.ros.org/question/113671/catkin-package-cannot-find-own-message-type-python/ 原因是因为.py ...

  10. js 验证图片

    var selectedImg = e.target.files[0]; //获取图片 var isPic = /^(image\/bmp|image\/gif|image\/jpeg|image\/ ...