《java设计模式》之责任链模式
在阎宏博士的《JAVA与模式》一书中开头是这样描述责任链(Chain of Responsibility)模式的:
责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
在以下条件下可考虑使用Chain of Responsibility:
1 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
2 你想在不明确指定接受者的情况下,想过个对象中的一个提交一个请求。
3 可处理一个请求的对象集合应该被动态指定。
一个简单的例子:
1 abstract class Handler { 2 3 private Handler nextHandler; 4 5 public Handler getNextHandler() { 6 return nextHandler; 7 } 8 9 public void setNextHandler(Handler nextHandler) { 10 this.nextHandler = nextHandler; 11 } 12 13 public abstract void doHandler(); 14 15 } 16 17 class ConcreteHandler extends Handler { 18 19 @Override 20 public void doHandler() { 21 22 if (getNextHandler() != null) { 23 24 System.out.println("还有责任链"); 25 getNextHandler().doHandler(); 26 } else { 27 28 System.out.println("我自己处理" + toString()); 29 } 30 31 } 32 }
既然为设计模式,必然有其鲜明代码的主体框架,我们来分析下
首先定义一个抽象的处理角色Handler ,其次是具体实现类ConcreteHandler ,在ConcreteHandler 我们通过getNextHandler()来判断是否还有下一个责任链,如果有,则继续
传递下去,调用getNextHandler().doHandler()来实现。
分析了简单的责任链模式的代码框架之后,我们接下来给代码加点实际的功能,举个很简单的例子,就是报销流程,项目经理<部门经理<总经理
其中项目经理报销额度不能大于500,则部门经理的报销额度是不大于1000,超过1000则需要总经理审核
1 abstract class ConsumeHandler { 2 3 private ConsumeHandler nextHandler; 4 5 public ConsumeHandler getNextHandler() { 6 return nextHandler; 7 } 8 9 public void setNextHandler(ConsumeHandler nextHandler) { 10 this.nextHandler = nextHandler; 11 } 12 13 /** user申请人 free报销费用 */ 14 public abstract void doHandler(String user, double free); 15 16 } 17 //项目经理 18 class ProjectHandler extends ConsumeHandler { 19 20 @Override 21 public void doHandler(String user, double free) { 22 if (free < 500) { 23 24 if (user.equals("lwx")) { 25 System.out.println("给予报销:" + free); 26 } else { 27 System.out.println("报销不通过"); 28 } 29 30 } else { 31 if (getNextHandler() != null) { 32 33 getNextHandler().doHandler(user, free); 34 } 35 } 36 37 } 38 } 39 //部门经理 40 class DeptHandler extends ConsumeHandler { 41 42 @Override 43 public void doHandler(String user, double free) { 44 if (free < 1000) { 45 46 if (user.equals("zy")) { 47 System.out.println("给予报销:" + free); 48 } else { 49 System.out.println("报销不通过"); 50 } 51 52 } else { 53 if (getNextHandler() != null) { 54 55 getNextHandler().doHandler(user, free); 56 } 57 } 58 59 } 60 } 61 //总经理 62 class GeneralHandler extends ConsumeHandler { 63 64 @Override 65 public void doHandler(String user, double free) { 66 if (free >=1000) { 67 68 if (user.equals("lwxzy")) { 69 System.out.println("给予报销:" + free); 70 } else { 71 System.out.println("报销不通过"); 72 } 73 74 } else { 75 if (getNextHandler() != null) { 76 77 getNextHandler().doHandler(user, free); 78 } 79 } 80 81 } 82 }
测试下
1 public static void main(String[] args) { 2 3 /*ConcreteHandler handler1 = new ConcreteHandler(); 4 ConcreteHandler handler2 = new ConcreteHandler(); 5 handler1.setNextHandler(handler2); 6 handler1.doHandler();*/ 7 8 ProjectHandler projectHandler =new ProjectHandler(); 9 DeptHandler deptHandler =new DeptHandler(); 10 GeneralHandler generalHandler =new GeneralHandler(); 11 projectHandler.setNextHandler(deptHandler); 12 deptHandler.setNextHandler(generalHandler); 13 projectHandler.doHandler("lwx", 450); 14 projectHandler.doHandler("lwx", 600); 15 projectHandler.doHandler("zy", 600); 16 projectHandler.doHandler("zy", 1500); 17 projectHandler.doHandler("lwxzy", 1500); 18 }
执行结果
给予报销:450.0
报销不通过
给予报销:600.0
报销不通过
给予报销:1500.0
拓展联想:模拟实现servlet过滤器中字符和登陆过滤器的实现
关于tomcat中责任链的使用:http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html