在上一节的拦截器中提到,程序的设计者一般会用拦截器替替代动态代理,将动态代理的逻辑隐藏起来,而把拦截器接口提供给开发者,使开发者不需要关系动态代理的具体实现过程,但是有时候需要多个拦截器,而且拦截器之间会相互依赖,比如我们从公司的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. http://www.2cto.com/ 红黑联盟

    http://www.2cto.com/ 红黑联盟,一个不错的学习或者开阔眼界的网站,内部由中文书写.比较适合国人.

  2. iOS开发之SceneKit框架--SCNParametricGeometry.h

    1.SCNParametricGeometry简介 SCNParametricGeometry用于创建简单的3D模型,比如SCNPlane 平面.SCNPyramid 锥形(金字塔).SCNBox 立 ...

  3. JAVA基础_类加载器

    什么是类加载器 类加载器是Java语言在1.0版本就引入的.最初是为了满足JavaApplet需要.现在类加载器在Web容器和OSGI中得到了广泛的应用,一般来说,Java应用的开发人员不需要直接同类 ...

  4. Linux文本编辑命令

    sort 排序工具,比较排序(根据字典排序) -t 指定分隔符(默认是空格) -k 指定第几域排序(默认第一域) -n 以数字大小排序 -r 逆向排序 -v 去掉重复行 -o 输出到文件中 -c 测试 ...

  5. linux sudo命令失败 提示sudo:/usr/bin/sudo 必须属于用户 ID 0(的用户)并且设置 setuid 位

    sudo:/usr/bin/sudo 必须属于用户 ID 0(的用户)并且设置 setuid 位 一.前言 这是一个神奇的错误,缘由是因为有人将/usr/bin/sudo的权限改为777或其他. 解决 ...

  6. html--伪等高布局

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  7. LUOGU P1514 引水入城 (bfs)

    传送门 解题思路 拉了很长的战线,换了好几种写法终于过了..首先每个蓄水场一定是对沙漠造成连续一段的贡献,所以可以$bfs$出每种状态,然后做一次最小区间覆盖,但这样的复杂度有点高.就每次只搜那些比左 ...

  8. LUOGU P1337 [JSOI2004]平衡点 / 吊打XXX(模拟退火)

    传送门 解题思路 学习了一下玄学算法--模拟退火,首先要求平衡处,也就是求势能最小的地方,就是求这个点到所有点的距离*重量最小.剩下的几乎是模拟退火的板子了. #include<iostream ...

  9. JavaSE_11_File类、递归

    1.1 概述File类 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. 1.2 构造方法 public File(String pathname ...

  10. Maven的作用及简介

    Maven的作用及简介 一.maven作用 项目之间都是有依赖的,比如A项目依赖于B项目,B项目依赖与C.D项目,等等.这样的依赖链可能很长. 但是,没有一个项目的jar包我们都要导入进去,我们要做的 ...