简单的应用举例:
参考文章:
http://blog.csdn.net/jason0539/article/details/45091639
http://www.cnblogs.com/kym/archive/2009/04/06/1430078.html
请假这个事情,相信每个人都不陌生。
在公司里,如果请假时间小于0.5天,那么只需要向项目经理打声招呼就OK了。
如果超过了0.5天,但是还小于2天,那么就要去找人事部处理,当然,这就要扣工资了。
如果超过了2天,你就需要去找总经理了,工资当然也玩完了。
那么,对于我们来说,这个流程就是这样的。
也就是这样一个过程,你需要和你的直接上级——项目经理去打交道,最终可能是项目经理给你回邮件,可能是人事部给你回邮件,也可能是总经理给你回邮件。内部的过程其实应该是个黑盒子,你并不知道内部的消息是如何处理的。你需要找到的,只是你想要第一个交付的对象而已。
借上面的例子解释下什么是责任链模式?
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。
即员工请假时向上层传递请求,上级(项目经理,部门经理,hr)都可以选择处理这个请求或者指定处理对象。直到这个请求被处理为止。
UML图
参与者:
Handler: 抽象处理者。定义了一个处理请求的方法。所有的处理者都必须实现该抽象类。
ConcreteHandler: 具体处理者。处理它所负责的请求,同时也可以访问它的后继者。如果它能够处理该请求则处理,否则将请求传递到它的后继者。
Client: 客户类。
职责链模式描述的请求如何沿着对象所组成的链来传递的。它将对象组成一条链,发送者将请求发给链的第一个接收者,并且沿着这条链传递,直到有一个对象来处理它或者直到最后也没有对象处理而留在链末尾端。
避 免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止,这就是职责链模 式。在职责链模式中,使得每一个对象都有可能来处理请求,从而实现了请求的发送者和接收者之间的解耦。同时职责链模式简化了对象的结构,它使得每个对象都 只需要引用它的后继者即可,而不必了解整条链,这样既提高了系统的灵活性也使得增加新的请求处理类也比较方便。但是在职责链中我们不能保证所有的请求都能 够被处理,而且不利于观察运行时特征。
代码举例:
抽象的Handle角色:
1 public abstract class Handler { 2 3 /** 4 * 持有后继的责任对象 5 */ 6 protected Handler successor; 7 /** 8 * 示意处理请求的方法,虽然这个示意方法是没有传入参数的 9 * 但实际是可以传入参数的,根据具体需要来选择是否传递参数 10 */ 11 public abstract void handleRequest(); 12 /** 13 * 取值方法 14 */ 15 public Handler getSuccessor() { 16 return successor; 17 } 18 /** 19 * 赋值方法,设置后继的责任对象 20 */ 21 public void setSuccessor(Handler successor) { 22 this.successor = successor; 23 } 24 25 }
具体处理者角色:
1 public class ConcreteHandler extends Handler { 2 /** 3 * 处理方法,调用此方法处理请求 4 */ 5 @Override 6 public void handleRequest() { 7 /** 8 * 判断是否有后继的责任对象 9 * 如果有,就转发请求给后继的责任对象 10 * 如果没有,则处理请求 11 */ 12 if(getSuccessor() != null) 13 { 14 System.out.println("放过请求"); 15 getSuccessor().handleRequest(); 16 }else 17 { 18 System.out.println("处理请求"); 19 } 20 } 21 22 }
客户端类:
1 public class Client { 2 3 public static void main(String[] args) { 4 //组装责任链 5 Handler handler1 = new ConcreteHandler(); 6 Handler handler2 = new ConcreteHandler(); 7 handler1.setSuccessor(handler2); 8 //提交请求 9 handler1.handleRequest(); 10 } 11 12 }
可以看出,客户端创建了两个处理者对象,并指定第一个处理者对象的下家是第二个处理者对象,而第二个处理者对象没有下家。然后客户端将请求传递给第一个处理者对象。
由于本示例的传递逻辑非常简单:只要有下家,就传给下家处理;如果没有下家,就自行处理。
因此,第一个处理者对象接到请求后,会将请求传递给第二个处理者对象。由于第二个处理者对象没有下家,于是自行处理请求。
代码示例2:申请聚餐
申请聚餐费用的管理,申请聚餐费用的大致流程一般是,由申请人先填写申请单,然后交给领导审批,如果申请批准下来,领导会通知申请人审批通过,然后申请人去财务领取费用,如果没有批准下来,领导会通知申请人审批未通过,此事也就此作罢。
不同级别的领导,对于审批的额度是不一样的,比如,项目经理只能审批500元以内的申请;部门经理能审批1000元以内的申请;而总经理可以审核任意额度的申请。
当某人提出聚餐费用申请的请求后,该请求会经由项目经理、部门经理、总经理之中的某一位领导来进行相应的处理,但是提出申请的人并不知道最终会由谁来处理 他的请求,一般申请人是把自己的申请提交给项目经理,或许最后是由总经理来处理他的请求。申请人只要直接与项目经理交互就可以,其余的工作在黑盒中,究竟 流程是怎样的,最后是由谁审批通过的,申请人无需关心。
uml图:
代码:
抽象处理者角色类
1 public abstract class Handler { 2 /** 3 * 持有下一个处理请求的对象 4 */ 5 protected Handler successor = null; 6 /** 7 * 取值方法 8 */ 9 public Handler getSuccessor() { 10 return successor; 11 } 12 /** 13 * 设置下一个处理请求的对象 14 */ 15 public void setSuccessor(Handler successor) { 16 this.successor = successor; 17 } 18 /** 19 * 处理聚餐费用的申请 20 * @param user 申请人 21 * @param fee 申请的钱数 22 * @return 成功或失败的具体通知 23 */ 24 public abstract String handleFeeRequest(String user , double fee); 25 }
具体处理者角色类
ProjectManager
1 public class ProjectManager extends Handler { 2 3 @Override 4 public String handleFeeRequest(String user, double fee) { 5 6 String str = ""; 7 //项目经理权限比较小,只能在500以内 8 if(fee < 500) 9 { 10 //为了测试,简单点,只同意张三的请求 11 if("张三".equals(user)) 12 { 13 str = "成功:项目经理同意【" + user + "】的聚餐费用,金额为" + fee + "元"; 14 }else 15 { 16 //其他人一律不同意 17 str = "失败:项目经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元"; 18 } 19 }else 20 { 21 //超过500,继续传递给级别更高的人处理 22 if(getSuccessor() != null) 23 { 24 return getSuccessor().handleFeeRequest(user, fee); 25 } 26 } 27 return str; 28 } 29 30 }
DeptManager
1 public class DeptManager extends Handler { 2 3 @Override 4 public String handleFeeRequest(String user, double fee) { 5 6 String str = ""; 7 //部门经理的权限只能在1000以内 8 if(fee < 1000) 9 { 10 //为了测试,简单点,只同意张三的请求 11 if("张三".equals(user)) 12 { 13 str = "成功:部门经理同意【" + user + "】的聚餐费用,金额为" + fee + "元"; 14 }else 15 { 16 //其他人一律不同意 17 str = "失败:部门经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元"; 18 } 19 }else 20 { 21 //超过1000,继续传递给级别更高的人处理 22 if(getSuccessor() != null) 23 { 24 return getSuccessor().handleFeeRequest(user, fee); 25 } 26 } 27 return str; 28 } 29 30 }
GeneralManager
1 public class GeneralManager extends Handler { 2 3 @Override 4 public String handleFeeRequest(String user, double fee) { 5 6 String str = ""; 7 //总经理的权限很大,只要请求到了这里,他都可以处理 8 if(fee >= 1000) 9 { 10 //为了测试,简单点,只同意张三的请求 11 if("张三".equals(user)) 12 { 13 str = "成功:总经理同意【" + user + "】的聚餐费用,金额为" + fee + "元"; 14 }else 15 { 16 //其他人一律不同意 17 str = "失败:总经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元"; 18 } 19 }else 20 { 21 //如果还有后继的处理对象,继续传递 22 if(getSuccessor() != null) 23 { 24 return getSuccessor().handleFeeRequest(user, fee); 25 } 26 } 27 return str; 28 } 29 30 }
客户端类
1 public class Client { 2 3 public static void main(String[] args) { 4 //先要组装责任链 5 Handler h1 = new GeneralManager(); 6 Handler h2 = new DeptManager(); 7 Handler h3 = new ProjectManager(); 8 h3.setSuccessor(h2); 9 h2.setSuccessor(h1); 10 11 //开始测试 12 String test1 = h3.handleFeeRequest("张三", 300); 13 System.out.println("test1 = " + test1); 14 String test2 = h3.handleFeeRequest("李四", 300); 15 System.out.println("test2 = " + test2); 16 System.out.println("---------------------------------------"); 17 18 String test3 = h3.handleFeeRequest("张三", 700); 19 System.out.println("test3 = " + test3); 20 String test4 = h3.handleFeeRequest("李四", 700); 21 System.out.println("test4 = " + test4); 22 System.out.println("---------------------------------------"); 23 24 String test5 = h3.handleFeeRequest("张三", 1500); 25 System.out.println("test5 = " + test5); 26 String test6 = h3.handleFeeRequest("李四", 1500); 27 System.out.println("test6 = " + test6); 28 } 29 30 }
职责链灵活在哪
1. 改变内部的传递规则
在内部,项目经理完全可以跳过人事部到那一关直接找到总经理。
每个人都可以去动态地指定他的继任者。
2. 可以从职责链任何一关开始。
如果项目经理不在,可以直接去找部门经理,责任链还会继续,没有影响。
3.用与不用的区别
不用职责链的结构,我们需要和公司中的每一个层级都发生耦合关系。
如果反映在代码上即使我们需要在一个类中去写上很多丑陋的if….else语句。
如果用了职责链,相当于我们面对的是一个黑箱,我们只需要认识其中的一个部门,然后让黑箱内部去负责传递就好了
纯的与不纯的责任链模式
一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,而是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的情况。
在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。
纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。