设计模式(14)---职责链模式
职责链模式 Chain of Responsibility (行为型模式)
1.概述
职责链模式:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
例如:员工请假天数小于3天,需要主任审批该假条;如果员工请假天数大于等于3天,小于10天,需要经理审批;如果员工请假天数大于等于10天,小于30天,需要老总审批;这条链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并让请求沿着链传递,由链上的处理者对请求进行相应的处理,客户端无须关心请求的处理细节以及请求的传递,只需将请求发送到链上即可,实现请求发送者和请求处理者解耦。
例如:斗地主,牌作为一个请求沿着一条链在传递,每一位纸牌的玩家都可以处理该请求。
2.结构图
3.代码
1 /* 2 * 请求类 3 */ 4 public class Request { 5 6 private int day ; 7 private String name ; 8 9 public Request(int day , String name) { 10 this.day = day; 11 this.name = name ; 12 } 13 14 public int getDay() { 15 return day; 16 } 17 public void setDay(int day) { 18 this.day = day; 19 } 20 21 public String getName() { 22 return name; 23 } 24 25 public void setName(String name) { 26 this.name = name; 27 } 28 29 30 31 32 }
1 /* 2 * 抽象处理类 3 */ 4 public abstract class Handler { 5 6 protected Handler successor ; //一个处理对象的后继 7 public Handler() { 8 9 } 10 11 public void setSuccessor(Handler successor) { 12 this.successor = successor; 13 } 14 15 //抽象请求处理方法 16 public abstract void handlerRequest(Request request) ; 17 18 }
1 /* 2 * 具体处理类A 3 */ 4 public class ConcreteHandlerA extends Handler { 5 6 public ConcreteHandlerA() { 7 // TODO Auto-generated constructor stub 8 } 9 10 @Override 11 public void handlerRequest(Request request) { 12 if (request.getDay() < 3){ 13 System.out.println("主任同意"+request.getName()+"请假"+request.getDay()+"天"); 14 }else{ 15 this.successor.handlerRequest(request); 16 } 17 18 } 19 20 }
1 /* 2 * 具体处理类B 3 */ 4 public class ConcreteHandlerB extends Handler { 5 6 public ConcreteHandlerB() { 7 // TODO Auto-generated constructor stub 8 } 9 10 @Override 11 public void handlerRequest(Request request) { 12 if (request.getDay() >= 3 && request.getDay() < 10){ 13 System.out.println("经理同意"+request.getName()+"请假"+request.getDay()+"天"); 14 }else{ 15 this.successor.handlerRequest(request); 16 } 17 18 } 19 20 }
1 /* 2 * 具体处理类C 3 */ 4 public class ConcreteHandlerC extends Handler { 5 6 public ConcreteHandlerC() { 7 // TODO Auto-generated constructor stub 8 } 9 10 @Override 11 public void handlerRequest(Request request) { 12 if (request.getDay() >= 10 && request.getDay() < 30){ 13 System.out.println("老总同意"+request.getName()+"请假"+request.getDay()+"天"); 14 } 15 16 } 17 18 }
1 public class Test { 2 3 public static void main(String[] args) { 4 Handler zhuren,jingli,laozong; 5 zhuren = new ConcreteHandlerA() ; 6 jingli = new ConcreteHandlerB() ; 7 laozong = new ConcreteHandlerC() ; 8 9 //创建职责链 10 zhuren.setSuccessor(jingli); 11 jingli.setSuccessor(laozong); 12 13 //创建请求 14 Request request1 = new Request(2, "员工a") ; 15 zhuren.handlerRequest(request1);//主任同意员工a请假2天 16 17 Request request2 = new Request(6, "员工b") ; 18 zhuren.handlerRequest(request2);//经理同意员工b请假6天 19 20 Request request3 = new Request(16, "员工c") ; 21 zhuren.handlerRequest(request3);//老总同意员工c请假16天 22 23 } 24 25 }
4.优点
(1) 职责链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构,由客户端负责链的创建,降低了系统的耦合度。
(2) 请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象的相互连接。
(3) 使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。
(4) 在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看是符合“开闭原则”的。
5.适用场景
(1) 有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定,客户端只需将请求提交到链上,而无须关心请求的处理对象是谁以及它是如何处理的。
(2) 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。