【前言】 本人从事了.net开发近10年,现在从.net转型到Java不足2月,所以所见所想都带着很深的.net烙印,不过也有很大可能是java翻译成.net,之后我又给转回java了。
【责任链模式】
外置方式
传统的责任链模式是一个请求有很多处理类,将这些处理类排列成一个顺序数组,如果某一个处理类能够处理,则中止请求;如果不能,则依次继续请求直到全部请求完毕。
用代码表示,就是如下所示:
1 //上下文环境 2 public class Context { 3 public String getHandlerName() { 4 return handlerName; 5 } 6 7 public void setHandlerName(String handlerName) { 8 this.handlerName = handlerName; 9 }10 11 public String getHandlerResult() {12 return handlerResult;13 }14 15 public void setHandlerResult(String handlerResult) {16 this.handlerResult = handlerResult;17 }18 19 public boolean isHasHandled() {20 return hasHandled;21 }22 23 public void setHasHandled(boolean hasHandled) {24 this.hasHandled = hasHandled;25 }26 27 String handlerName;28 29 String handlerResult;30 31 boolean hasHandled;32 33 }34 //接口35 public interface IOuterHandler {36 boolean canHandler(Context context);37 38 void handler(Context context);39 }
1 //实现类A 2 public class AOuterHandler implements IOuterHandler { 3 4 private static String HandleName="A"; 5 6 @Override 7 public boolean canHandler(Context context) { 8 return context.getHandlerName()==HandleName; 9 }10 11 @Override12 public void handler(Context context) {13 context.setHandlerResult("没错,就是我处理的:"+this.getClass().getSimpleName());14 context.setHasHandled(true);15 }16 }17 18 //实现类B19 public class BOuterHandler implements IOuterHandler {20 private static String HandleName="B";21 22 @Override23 public boolean canHandler(Context context) {24 return context.getHandlerName()==HandleName;25 }26 27 @Override28 public void handler(Context context) {29 context.setHandlerResult("没错,就是我处理的:"+this.getClass().getSimpleName());30 context.setHasHandled(true);31 }32 }33 34 //实现类C35 public class COuterHandler implements IOuterHandler {36 private static String HandleName="C";37 38 @Override39 public boolean canHandler(Context context) {40 return context.getHandlerName()==HandleName;41 }42 43 @Override44 public void handler(Context context) {45 context.setHandlerResult("没错,就是我处理的:"+this.getClass().getSimpleName());46 context.setHasHandled(true);47 }48 }
之后我们就需要将这些处理类组装成责任链进行处理,具体代码如下:
1 public class Executor { 2 public static void main(String[] args){ 3 ArrayListhandlers=getHandlers(); 4 Context context1=new Context(); 5 context1.setHandlerName("A"); 6 System.out.println(Exe(handlers,context1).getHandlerResult()); 7 8 Context context2=new Context(); 9 context2.setHandlerName("C");10 System.out.println(Exe(handlers,context2).getHandlerResult());11 }12 13 private static ArrayList getHandlers() {14 ArrayList handlers = new ArrayList<>();15 handlers.add(new AOuterHandler());16 handlers.add(new BOuterHandler());17 handlers.add(new COuterHandler());18 return handlers;19 }20 21 private static Context exe(ArrayList handlers,Context context){22 if(handlers!=null&&handlers.size()!=0){23 handlers.forEach(handler->{24 if(context.isHasHandled()){25 return;26 }27 if(handler.canHandler(context)){28 handler.handler(context);29 }30 });31 }32 return context;33 }34 }
我们可以看见,exe方法就是实现的主体(这里用了foreach函数,所以没有进行短路处理,实际上如果context.isHasHandled==true后,没有必要进行后面的循环),原则就是当前类是否能够处理,如果不能,就交付给下一个处理函数,当然可能是到最后也没有被处理,这种情况可以不处理直接返回,也可能是使用默认处理函数,不过这不重要了。这种处理方式是存在缺陷的,就是俩个handler想联合处理,是做不到的。所以责任链模式,就发展出内置的形式。
内置方式
内置方式还是看代码:
//Contenx略,见上文public interface IInnerHandler { void setHandler(IInnerHandler handler); void hanlder(Context context);}
1 //类A 2 public class AInnerHandler implements IInnerHandler { 3 private static String HandleName="A"; 4 private IInnerHandler handler; 5 6 @Override 7 public void setHandler(IInnerHandler handler) { 8 this.handler=handler; 9 }10 11 @Override12 public void hanlder(Context context) {13 if(context.getHandlerName().equals(HandleName)){14 context.setHandlerResult("没错,就是我处理的:"+this.getClass().getSimpleName());15 //不需要这句,因为没有意义了16 //context.setHasHandled(true);17 }else {18 handler.hanlder(context);19 }20 }21 22 //类B23 public class BInnerHandler implements IInnerHandler {24 private static String HandleName="A";25 private static String HandleName2="C";26 private IInnerHandler handler;27 28 @Override29 public void setHandler(IInnerHandler handler) {30 this.handler=handler;31 }32 33 @Override34 public void hanlder(Context context) {35 if(HandleName.equals(context.getHandlerName())||HandleName2.equals(context.getHandlerName())){36 for (int i=0;i<3;i++){37 handler.hanlder(context);38 }39 }40 }41 }42 //类C43 44 public class CInnerHandler implements IInnerHandler {45 private static String HandleName="C";46 private IInnerHandler handler;47 48 @Override49 public void setHandler(IInnerHandler handler) {50 this.handler=handler;51 }52 53 @Override54 public void hanlder(Context context) {55 if(context.getHandlerName().equals(HandleName)){56 String resultInfo="***没错,就是我处理的:"+this.getClass().getSimpleName();57 if(context.getHandlerResult()==null){58 context.setHandlerResult(resultInfo);59 }else {60 context.setHandlerResult(context.getHandlerResult() + "\n" + resultInfo);61 }62 }else {63 handler.hanlder(context);64 }65 }66 }
之后我们将内置实现类组合实现责任链处理
1 public class Executor { 2 public static void main(String[] args){ 3 IInnerHandler handler=getHandler(); 4 5 Context context1=new Context(); 6 context1.setHandlerName("A"); 7 handler.hanlder(context1); 8 System.out.println(context1.getHandlerResult()); 9 10 Context context2=new Context();11 context2.setHandlerName("C");12 handler.hanlder(context2);13 System.out.println(context2.getHandlerResult());14 }15 16 private static IInnerHandler getHandler() {17 IInnerHandler aHandler=new AInnerHandler(),bHandler=new BInnerHandler(),cHandler=new CInnerHandler();18 bHandler.setHandler(cHandler);19 aHandler.setHandler(bHandler);20 return aHandler;21 }22 }
处理的结果如下:
我们可以看见,内置完全不同于外置,对于A、C类来说,他的作用就是处理,如果处理不了让下一个类处理,这和外置是类似的。但是B类,他可以自己处理,也可以和A,C联合处理。本例中,B就自己未做处理,只是让C处理了三次。所以明显可以看出内置功能更加强大。但是等等,像B,C这种组合,明显是装饰者模式,怎么是责任链呢?
【装饰者模式】
什么是装饰者?还是看代码吧
1 //上下文 2 public class Context { 3 private ArrayListarrayList=new ArrayList (); 4 public ArrayList getArrayList(){ 5 return arrayList; 6 } 7 public void add(String moreInfo){ 8 arrayList.add(moreInfo); 9 }10 }11 //装饰者接口12 public interface IDecorator {13 void setDecorator(IDecorator decorator);14 15 void domore(Context context);16 }
1 //ADecorator 2 public class ADecorator implements IDecorator { 3 IDecorator decorator; 4 5 public void setDecorator(IDecorator decorator) { 6 this.decorator = decorator; 7 } 8 9 public void domore(Context context) {10 context.add(this.getClass().getSimpleName());11 decorator.domore(context);12 context.add(this.getClass().getSimpleName());13 }14 }15 16 // BDecorator17 public class BDecorator implements IDecorator {18 IDecorator decorator;19 20 public void setDecorator(IDecorator decorator) {21 this.decorator = decorator;22 }23 24 public void domore(Context context) {25 context.add(this.getClass().getSimpleName());26 decorator.domore(context);27 context.add(this.getClass().getSimpleName());28 }29 }30 31 //CDecorator32 public class CDecorator implements IDecorator {33 IDecorator decorator;34 35 public void setDecorator(IDecorator decorator) {36 this.decorator = decorator;37 }38 39 public void domore(Context context) {40 context.add(this.getClass().getSimpleName());41 //decorator.domore(context);42 context.add("最后一项需要短路");43 context.add(this.getClass().getSimpleName());44 }45 }
装饰者装配和执行的代码如下:
1 public class Executor { 2 public static void main(String[] args) { 3 IDecorator decorator = getDecorator(); 4 Context context = new Context(); 5 decorator.domore(context); 6 context.getArrayList().forEach(mesage -> System.out.println(mesage)); 7 } 8 9 private static IDecorator getDecorator() {10 IDecorator ade = new ADecorator(),11 bad = new BDecorator(),12 cad = new CDecorator();13 bad.setDecorator(cad);14 ade.setDecorator(bad);15 return ade;16 }17 }
执行的结果:
【对比】
责任链(外置):有一个类负责任,在找到这个负责的类之前,其他的类都是看一样是否和自己有关。而找到这个负责的类后,一般也会短路,不会继续往下执行。所以从责任链重点在于谁负责。
装饰者:在构成的链路中,每一个类都发挥自己的作用,并且不会进行短路,直到最后一个类。
责任链(内置):和装饰者在接口层面,出来名字不同,没有什么不一样的。所以它是用装饰者的身体,装责任链的思想。是一个杂交体。至于是责任链还是装饰者,就看内部实现是否有短路,是否有具体负责任的。很可能是俩个都有。
【思考】
责任链和装饰者这种变形,是否是java中常用的,是否有其他变形的实现呢?答案是有,下节将让你看见不一样的责任链(装饰者)。