设计模式之禅之设计模式-责任链模式
一:责任链模式的定义
--->使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
--->责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果
--->一般会有一个封装类对责任模式进行封装,也就是替代Client类,直接返回链中的第一个处理者,具体链的设置不需要高层次模块关系,这样,更简化了高层次模块的调用,减少模块间的耦合,提高系统的灵活性。
二:责任链模式的应用
●责任链模式的优点
责任链模式非常显著的优点是将请求和处理分开。请求者可以不用知道是谁处理的,处理者可以不用知道请求的全貌(例如在J2EE项目开发中,可以剥离出无状态Bean由责任链处理),两者解耦,提高系统的灵活性。
●责任链模式的缺点
责任链有两个非常显著的缺点:一是性能问题,每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题。二是调试不很方便,特别是链条比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂。
三:责任链模式的注意事项
● 链中节点数量需要控制,避免出现超长链的情况,一般的做法是在Handler中设置一个最大节点数量,在setNext方法中判断是否已经是超过其阈值,超过则不允许该链建立,避免无意识地破坏系统性能。
● 作为请求者可以不用知道到底是需要谁来处理的,这是责任链模式的核心,同时责任链模式也可以作为一种补救模式来使用
四:责任链模式的实战
●在责任链模式中一个请求发送到链中后,前一节点消费部分消息,然后交由后续节点继续处理,最终可以有处理结果也可以没有处理结果,读者可以不用理会什么纯的、不纯的责任链模式
●这里也用到模板方法模式,在模板方法中判断请求的级别和当前能够处理的级别,如果相同则调用基本方法,做出反馈;如果不相等,则传递到下一个环节,由下一环节做出回应,如果已经达到环节结尾,则直接做不同意处理。
五:责任链模式的例子
【1】责任链模式的链条抽象类
1 package com.yeepay.sxf.template11; 2 /** 3 * 责任链条接口 4 * @author sxf 5 * 6 */ 7 public abstract class Handler { 8 //下一个处理者 9 private Handler nextHandler; 10 11 12 //责任链条 13 public final Response handleMessage(Request request){ 14 Response response=null; 15 //判断处理等级 16 if(this.getLeve().equals(request.getLeve())){ 17 //处理级别相符 18 response=this.echo(request); 19 }else{ 20 //不属于的处理级别 21 //判断是否有下一个处理者 22 if(this.nextHandler!=null){ 23 response=this.nextHandler.handleMessage(request); 24 }else{ 25 //没有适当处理者,业务自行处理 26 } 27 } 28 29 return response; 30 } 31 32 //获取当前处理者的处理等级 33 protected abstract String getLeve(); 34 //每个处理者都必须实现处理任务 35 protected abstract Response echo(Request request); 36 //设置下一个处理者 37 public void setNext(Handler handler){ 38 this.nextHandler=handler; 39 } 40 }
【2】责任链模式的请求包装
1 package com.yeepay.sxf.template11; 2 /** 3 * 请求的封装 4 * @author sxf 5 * 6 */ 7 public class Request { 8 //请求的等级 9 private String leve; 10 //请求内容 11 private String requestContext; 12 13 //有参数的构造 14 public Request(String leve, String requestContext) { 15 super(); 16 this.leve = leve; 17 this.requestContext = requestContext; 18 } 19 public String getLeve() { 20 return leve; 21 } 22 public void setLeve(String leve) { 23 this.leve = leve; 24 } 25 public String getRequestContext() { 26 return requestContext; 27 } 28 public void setRequestContext(String requestContext) { 29 this.requestContext = requestContext; 30 } 31 32 33 }
【3】责任链模式的响应包装
1 package com.yeepay.sxf.template11; 2 /** 3 * 响应的结果 4 * @author sxf 5 * 6 */ 7 public class Response { 8 //响应的内容 9 private String responseStr; 10 11 public String getResponseStr() { 12 return responseStr; 13 } 14 15 public void setResponseStr(String responseStr) { 16 this.responseStr = responseStr; 17 } 18 19 }
【4】第一个责任者
1 package com.yeepay.sxf.template11; 2 /** 3 * 父亲处理者 4 * @author sxf 5 * 6 */ 7 public class Father extends Handler { 8 private String leve="1"; 9 10 //返回处理等级 11 @Override 12 protected String getLeve() { 13 14 return leve; 15 } 16 17 //处理请求 18 @Override 19 protected Response echo(Request request) { 20 System.out.println("Father.echo(父亲已经处理===》)"+request.getRequestContext()); 21 Response response=new Response(); 22 response.setResponseStr("你的父亲已经处理的请求"); 23 return response; 24 } 25 26 27 }
【5】第二个责任者
1 package com.yeepay.sxf.template11; 2 /** 3 * 丈夫处理 4 * @author sxf 5 * 6 */ 7 public class Husband extends Handler{ 8 //丈夫处理等级 9 private String leve="2"; 10 11 //获取处理等级 12 @Override 13 protected String getLeve() { 14 return leve; 15 } 16 17 18 @Override 19 protected Response echo(Request request) { 20 System.out.println("Husband.echo(你的丈夫已经处理你的请求==>)"+request.getRequestContext()); 21 Response response=new Response(); 22 response.setResponseStr("你的丈夫已经处理你的请求"); 23 return response; 24 } 25 26 27 28 }
【6】客户端
1 package com.yeepay.sxf.template11; 2 3 public class ClientTest { 4 5 public static void main(String[] args) { 6 //请求 7 Request request=new Request("2", "我想出门逛街"); 8 //第一责任人 9 Handler handler=new Father(); 10 //第二责任人 11 Husband husband=new Husband(); 12 handler.setNext(husband); 13 14 //找第一责任人处理 15 Response response=handler.handleMessage(request); 16 17 //处理结果 18 System.out.println("ClientTest.main()"+response.getResponseStr()); 19 } 20 }