欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-04-01 08:22:12
【前言】 本人从事了.net开发近10年,现在从.net转型到Java不足2月,所以所见所想都带着很深的.net烙印,不过也有很大可能是java翻译成.net,之后我又给转回java了。 【责任链模式】 外置方式 传统的责任链模式是一个请求有很多处理类,将这些处理类排列成一个顺序数组,如果某一个处理 ......

【前言】 本人从事了.net开发近10年,现在从.net转型到java不足2月,所以所见所想都带着很深的.net烙印,不过也有很大可能是java翻译成.net,之后我又给转回java了。

【责任链模式】

外置方式

传统的责任链模式是一个请求有很多处理类,将这些处理类排列成一个顺序数组,如果某一个处理类能够处理,则中止请求;如果不能,则依次继续请求直到全部请求完毕。

用代码表示,就是如下所示:

【设计模式】1,责任链与装饰者模式(基本介绍)
 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,责任链与装饰者模式(基本介绍)
 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 }

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

我们可以看见,exe方法就是实现的主体(这里用了foreach函数,所以没有进行短路处理,实际上如果context.ishashandled==true后,没有必要进行后面的循环),原则就是当前类是否能够处理,如果不能,就交付给下一个处理函数,当然可能是到最后也没有被处理,这种情况可以不处理直接返回,也可能是使用默认处理函数,不过这不重要了。这种处理方式是存在缺陷的,就是俩个handler想联合处理,是做不到的。所以责任链模式,就发展出内置的形式。

内置方式

内置方式还是看代码:

【设计模式】1,责任链与装饰者模式(基本介绍)
//contenx略,见上文

public interface iinnerhandler {
    void  sethandler(iinnerhandler handler);
    void hanlder(context context);
}
内置接口
【设计模式】1,责任链与装饰者模式(基本介绍)
 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 }

处理的结果如下:

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

 我们可以看见,内置完全不同于外置,对于a、c类来说,他的作用就是处理,如果处理不了让下一个类处理,这和外置是类似的。但是b类,他可以自己处理,也可以和a,c联合处理。本例中,b就自己未做处理,只是让c处理了三次。所以明显可以看出内置功能更加强大。但是等等,像b,c这种组合,明显是装饰者模式,怎么是责任链呢?

【装饰者模式】

什么是装饰者?还是看代码吧

【设计模式】1,责任链与装饰者模式(基本介绍)
 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,责任链与装饰者模式(基本介绍)
 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 }

执行的结果:

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

 【对比】

责任链(外置):有一个类负责任,在找到这个负责的类之前,其他的类都是看一样是否和自己有关。而找到这个负责的类后,一般也会短路,不会继续往下执行。所以从责任链重点在于谁负责。

装饰者:在构成的链路中,每一个类都发挥自己的作用,并且不会进行短路,直到最后一个类。

责任链(内置):和装饰者在接口层面,出来名字不同,没有什么不一样的。所以它是用装饰者的身体,装责任链的思想。是一个杂交体。至于是责任链还是装饰者,就看内部实现是否有短路,是否有具体负责任的。很可能是俩个都有。

【思考】

责任链和装饰者这种变形,是否是java中常用的,是否有其他变形的实现呢?答案是有,下节将让你看见不一样的责任链(装饰者)