原型模式简单介绍【设计模式3】
前文回顾:
1 //上下文 2 public class Context { 3 public String getHandlerResult() { 4 return handlerResult; 5 } 6 7 public void setHandlerResult(String handlerResult) { 8 this.handlerResult = handlerResult; 9 } 10 11 private String handlerResult; 12 } 13 //Handler接口 14 public interface IHandler { 15 void handler(Context context); 16 } 17 //NullHandler 18 public class NullHandler implements IHandler { 19 @Override 20 public void handler(Context context) { 21 22 } 23 } 24 //Middleware接口 25 public interface IMiddleware { 26 IHandler handle(IHandler handler); 27 } 28 //MiddlewareCenter核心代码 29 public class MiddlewareCenter implements Cloneable { 30 private ArrayList<IMiddleware> middlewares = new ArrayList<>(); 31 32 public void userMiddleware(IMiddleware middleware) { 33 middlewares.add(middleware); 34 } 35 36 public IHandler build() { 37 IHandler handler = new NullHandler(); 38 Collections.reverse(middlewares); 39 for (IMiddleware middlerware : middlewares) { 40 handler = middlerware.handle(handler); 41 } 42 return handler; 43 } 44 45 @Override 46 protected Object clone() throws CloneNotSupportedException { 47 MiddlewareCenter middlewareCenter = new MiddlewareCenter(); 48 middlewareCenter.middlewares.addAll(this.middlewares); 49 return middlewareCenter; 50 } 51 }
1 //在MiddlewareCenter中的部分,提取出来放到helper类里 2 public class MiddlewareCenterHelper { 3 public static MiddlewareCenter use(MiddlewareCenter middlewareCenter, IHandler handler) { 4 middlewareCenter.userMiddleware(currenthandler -> { 5 return context -> { 6 handler.handler(context); 7 currenthandler.handler(context); 8 }; 9 }); 10 return middlewareCenter; 11 } 12 13 public static void run(MiddlewareCenter middlewareCenter, IHandler handler) { 14 middlewareCenter.userMiddleware(currenthandler -> { 15 return context -> { 16 handler.handler(context); 17 }; 18 }); 19 } 20 }
前情回顾1是原有代码,前情回顾2是后来代码略作修改,将MiddleWareCenter进行了分割,MiddleWareCenter只保存核心,MiddleWareCenterHelper是通过MiddleWareCenter的帮助类。
MiddleWareCenterHelper中现在实现俩个类:use(将handler加入到责任链中),run(将handler加入责任链中,并且后面的进行短路不再执行)。现在想要加入when方法,使when方法部分的handler能够根据条件(Config)动态决定是否执行。
when方法
when方法有俩个地方需要注意:
- when中可能是一个handler也可能是handler数组,甚至可能是IMiddlerWare对象。
- 判断是否能够执行,是运行过程中的config对象,不是初始的config对象
下面就是when方法的实现:
1 public class MiddlewareCenterHelper { 2 public static MiddlewareCenter use(MiddlewareCenter middlewareCenter, IHandler handler) { 3 //略 4 } 5 6 public static void run(MiddlewareCenter middlewareCenter, IHandler handler) { 7 //略 8 } 9 10 public static MiddlewareCenter when(MiddlewareCenter middlewareCenter, Consumer<MiddlewareCenter> config, Predicate<Context> predicate) { 11 try { 12 MiddlewareCenter center = (MiddlewareCenter) middlewareCenter.clone(); 13 config.accept(center); 14 middlewareCenter.userMiddleware(main -> { 15 IHandler branch = center.build(); 16 return context -> { 17 if (predicate.test(context)) { 18 branch.handler(context); 19 } else { 20 main.handler(context); 21 } 22 }; 23 }); 24 } catch (CloneNotSupportedException ex) { 25 26 } 27 return middlewareCenter; 28 } 29 }
when方法中,配置参数使用Consumer<T>,这是一个妙笔,在需要对对象进行配置的时候建议使用这个参数。
在when中,我们看见MiddlewareCenter center = (MiddlewareCenter) middlewareCenter.clone();这就是原型模式的典型写法(至于此处为什么不new MiddlewareCenter(),而要clone一个,如果new会导致责任链断裂,在when后面加入的handler不会被执行,具体解释略)。原型模式区别于直接new对象的地方在于,原型模式会保存对象内部的变量,而new原有属性都会被重置。当构造新对象的时候需要保留原有对象已经赋值的属性,就要使用原型模式。而Middleware中clone方法的实现如下所示:
1 public class MiddlewareCenter implements Cloneable { 2 //其他略 3 @Override 4 protected Object clone() throws CloneNotSupportedException { 5 MiddlewareCenter middlewareCenter = new MiddlewareCenter(); 6 middlewareCenter.middlewares.addAll(this.middlewares); 7 return middlewareCenter; 8 } 9 }
总结
原型模式只是简单实现一个clone方法(当然你也可以起名叫copy、getInstance等),在需要的时候对现有对象进行复制。但是在java上原型模式真的这么简单吗?
答案是否定的,在java上这点可以扩展很多内容。
1,构建对象有多少种方式呢?clone、new新对象还有别的吗?
2,clone为啥要实现Cloneable,我直接起名叫copy,不实现接口也不抛出异常不是更好吗?
3,什么是深复制,什么是浅复制
4,serializable深复制有什么注意的呢
下节请继续看往祖坟上刨根问底的原型模式