Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

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

Error message here!

返回登录

Close

你没见过的责任链设计模式!【设计模式2】

码对象 2019-02-15 08:49:00 阅读数:144 评论数:0 点赞数:0 收藏数:0

New责任链&装饰者】

感慨一下,本以为上下篇能一起发呢,结果要隔一定时间,传统的责任链与装饰者模式:https://www.cnblogs.com/SharePointApp/p/10340578.html

基本代码

现在要做的就是责任链如果使用外置模式,能不能像装饰者一样几个处理类联合处理?答案是可以的,不过就用到java8的特性,具体代码如下

1 //简化的上下文
2 public class Context {
3  String handlerResult;
4 }
5
6 //处理接口
7 public interface IHandler {
8 void handler(Context context);
9 }
接口与上下文
1 //默认Null接口实现
2 public class NullHandler implements IHandler {
3  @Override
4 public void handler(Context context) {
5
6  }
7 }
默认Null接口实现
1 //接口的链式结构
2 public interface IMiddleware {
3  IHandler handle(IHandler handler);
4 }
接口的链式结构
 1 //构建链式结构
 2 public class MiddlewareCenter {
 3 private ArrayList<IMiddleware> middlewares = new ArrayList<>();
 4
 5 public void userMiddleware(IMiddleware middleware) {
 6  middlewares.add(middleware);
 7  }
 8
 9 public void use(IHandler handler) {
10 this.userMiddleware(currenthandler -> {
11 return context -> {
12  handler.handler(context);
13  currenthandler.handler(context);
14  };
15  });
16  }
17
18 public void run(IHandler handler) {
19 this.userMiddleware(currenthandler -> {
20 return context -> {
21  handler.handler(context);
22  };
23  });
24  }
25
26 public IHandler build() {
27 IHandler handler = new NullHandler();
28  Collections.reverse(middlewares);
29 for (IMiddleware middlerware : middlewares) {
30 handler=middlerware.handle(handler);
31  }
32 return handler;
33  }
34 }
【重点】-链式结构的构建

下面贴的是测试代码,略显冗长

 1 public class Executor {
 2 public static void main(String[] args){
 3 Context context=new Context();
 4 context.handlerResult="";
 5 MiddlewareCenter center=new MiddlewareCenter();
 6  center.use(Executor::addString);
 7  center.use(Executor::addString2);
 8  center.use(Executor::modifyString);
 9  center.build().handler(context);
10  System.out.println(context.handlerResult);
11
12 Context context1=new Context();
13 context1.handlerResult="";
14 MiddlewareCenter center1=new MiddlewareCenter();
15  center1.use(Executor::addString);
16  center1.use(Executor::modifyString);
17  center1.use(Executor::addString2);
18  center1.build().handler(context1);
19  System.out.println(context1.handlerResult);
20
21 Context context2=new Context();
22 context2.handlerResult="";
23 MiddlewareCenter center2=new MiddlewareCenter();
24  center2.use(Executor::addString);
25  center2.run(Executor::modifyString);
26  center2.use(Executor::addString2);
27  center2.build().handler(context2);
28  System.out.println(context2.handlerResult);
29  }
30
31 private static void addString(Context context){
32 context.handlerResult=context.handlerResult+"addString;";
33  }
34
35 private static void addString2(Context context){
36 context.handlerResult=context.handlerResult+"addString2;";
37  }
38
39 private static void modifyString(Context context){
40 context.handlerResult=context.handlerResult.replace("addString","addString->modifyString");
41  }
42 }

执行结果如下:

代码解析

先说说好处:

  • 在Java8中,lamada表达式以及方法已经是一类公民,可以减少很多不必要的子类扩展。所以在组装的时候IHandler对象的时候,没有必要构建很多IHandler对象(传统的责任链、装饰者模式也可以,利用lamada表达式)。
  • 在MiddleWareCenter中,可以直接将IHandler对象组装在一起,和责任链模式外置类似,但是也可以用IMiddleWare对象,使用内置的方式将IHandler组装起来。使代码有很大的灵活性。
  • 总的说来就是使用的时候既简单,又强大,还有代码看起来更时髦。

缺点呢?

  • 相比于责任链内置、责任链外置、装饰者模式,没有什么缺点,不过代码略有一点难以理解

 核心代码解析

1 public IHandler build() {
2 IHandler handler = new NullHandler();
3  Collections.reverse(middlewares);
4 for (IMiddleware middlerware : middlewares) {
5 handler=middlerware.handle(handler);
6  }
7 return handler;
8 }

这句代码可能是最难以理解的,我们知道middlewares的类型是IArrayList<IMiddleWare>,所以这段代码就是翻转集合,之后遍历组装。怎么遍历组装的,就得用数学知识进行简单的讲解了

我们知道IMiddleWare的handler方法是一个IHandler到IHandler的函数(略思考,这没难度),我们将IHandler用自变量X代替,所以IArrayList<IMiddleWare>就是函数F(X)的集合(假设里面的函数是A(X)、B(X)、C(X))。

翻转集合之后,遍历组装的结果是C(B(A(X))),这是一个复合函数,但是本质上还是一个F(X),即IHandler到IHandler的函数。而IHandler到IHandler的函数,我们给X的值就是NullHandler,所以带入复合函数C(B(A(X)))后得到C(B(A(NullHandler)))。这个结果是一个IHandler对象,他可以用于处理Context上下文。

哎,感觉数学还是要学好,虽然你可以不懂,但是底层都有数学基础做支撑的。另外设计模式看类图已经没那么实用了,因为方法成为第一等公民后,函数编程已经来临,大部分设计模式可能都会有新的表述

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

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