java责任链模式
接下来我们将要谈谈责任链模式,有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。但是发出者并不清楚到底最终那个对象会处理该请求,所以,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整。先看看关系图:
Abstracthandler类提供了get和set方法,方便MyHandle类设置和修改引用对象,MyHandle类是核心,实例化后生成一系列相互持有的对象,构成一条链。
- public interface Handler {
- public void operator();
- }
- public abstract class AbstractHandler {
- private Handler handler;
- public Handler getHandler() {
- return handler;
- }
- public void setHandler(Handler handler) {
- this.handler = handler;
- }
- }
- public class MyHandler extends AbstractHandler implements Handler {
- private String name;
- public MyHandler(String name) {
- this.name = name;
- }
- @Override
- public void operator() {
- System.out.println(name+"deal!");
- if(getHandler()!=null){
- getHandler().operator();
- }
- }
- }
- public class Test {
- public static void main(String[] args) {
- MyHandler h1 = new MyHandler("h1");
- MyHandler h2 = new MyHandler("h2");
- MyHandler h3 = new MyHandler("h3");
- h1.setHandler(h2);
- h2.setHandler(h3);
- h1.operator();
- }
- }
输出:
h1deal!
h2deal!
h3deal!
此处强调一点就是,链接上的请求可以是一条链,可以是一个树,还可以是一个环,模式本身不约束这个,需要我们自己去实现,同时,在一个时刻,命令只允许由一个对象传给另一个对象,而不允许传给多个对象。
===============================================================================================================================================
在阎宏博士的《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过滤器中字符和登陆过滤器的实现