Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

责任链与装饰者模式(基本介绍)【设计模式1】

码对象 2019-02-13 16:04:00 阅读数:165 评论数:0 点赞数:0 收藏数:0

【前言】 本人从事了.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  @Override
12 public void handler(Context context) {
13 context.setHandlerResult("没错,就是我处理的:"+this.getClass().getSimpleName());
14 context.setHasHandled(true);
15  }
16 }
17
18 //实现类B
19 public class BOuterHandler implements IOuterHandler {
20 private static String HandleName="B";
21
22  @Override
23 public boolean canHandler(Context context) {
24 return context.getHandlerName()==HandleName;
25  }
26
27  @Override
28 public void handler(Context context) {
29 context.setHandlerResult("没错,就是我处理的:"+this.getClass().getSimpleName());
30 context.setHasHandled(true);
31  }
32 }
33
34 //实现类C
35 public class COuterHandler implements IOuterHandler {
36 private static String HandleName="C";
37
38  @Override
39 public boolean canHandler(Context context) {
40 return context.getHandlerName()==HandleName;
41  }
42
43  @Override
44 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 ArrayList<IOuterHandler> handlers=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<IOuterHandler> getHandlers() {
14 ArrayList<IOuterHandler> 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<IOuterHandler> 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  @Override
12 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 //类B
23 public class BInnerHandler implements IInnerHandler {
24 private static String HandleName="A";
25 private static String HandleName2="C";
26 private IInnerHandler handler;
27
28  @Override
29 public void setHandler(IInnerHandler handler) {
30 this.handler=handler;
31  }
32
33  @Override
34 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 //类C
43
44 public class CInnerHandler implements IInnerHandler {
45 private static String HandleName="C";
46 private IInnerHandler handler;
47
48  @Override
49 public void setHandler(IInnerHandler handler) {
50 this.handler=handler;
51  }
52
53  @Override
54 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 ArrayList<String> arrayList=new ArrayList<String>();
 4 public ArrayList<String> 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 // BDecorator
17 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 //CDecorator
32 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中常用的,是否有其他变形的实现呢?答案是有,下节将让你看见不一样的责任链(装饰者)

版权声明
本文为[码对象]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/SharePointApp/p/10340578.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领