高效的策略模式设计方法
在实现策略模式的时候,我们习惯用switch-case来代替if-else if-else,在代码结构上会更加清晰,但这也只是从代码结构这个层面上来考虑,我们可以从代码速度上来考虑设计问题。
无论是switch-case还是if-else if-else的设计,都会遇到一个问题:如果判断的条件很多,假设是n个,而满足的条件恰好是最后一个,那么代码的执行效率就是o(n)。
为了找到一个能够执行的代码,我们实际上是判断了n次,当然,这个判断其实是很快的,一般情况下的效率折损是不用考虑的,就算判断条件很多,但涉及那么多判断条件的业务场景,本身就是个灾难了。
我们可以通过一种数据结构来解决这个问题。
策略模式的目的就是根据某种类型寻找对应的策略,如果将该类型理解为key,而策略就是value的话,我们很快就能明白,这就是key-value的查找。
key-value的容器类自然想到HashMap。
在我们之前的文章 http://www.cnblogs.com/wenjiang/p/6019000.html 中提到了一个业务场景,就是根据对应的广告平台寻找对应的平台调用方法。这里利用HashMap来重新整理我们的代码结构。
我们定义了Enum类ShowType表示要展示的广告类型,然后各种类型的Controller就是对应的策略类。
Map<ShowType, Object> controllerMap = new HashMap(); controllerMap.put(ShowType.Banner, createBannerProperties(activity, slotId, viewGroup, platforms); ...
我们定义一个ShowType为key值,Controller为value值的HashMap,然后将对应的key-value放进去。
原先我们是根据传进来的ShowType返回对应的Controller:
1 Object controller = null; 2 switch (showType) { 3 case Banner: 4 properties = createBannerProperties(activity, slotId, viewGroup, platforms); 5 controller = ((BannerProperties) properties).getController(); 6 break; 7 case Feed: 8 properties = createFeedProperties(activity, slotId, platforms); 9 controller = ((MMUFeedProperties) properties).getController(); 10 break; 11 case Insert: 12 properties = createInsertProperties(activity, slotId, platforms); 13 controller = ((InsertProperties) properties).getController(); 14 break; 15 case LoopImage: 16 properties = createLoopImageProperties(activity, slotId, viewGroup, platforms); 17 break; 18 case Welcome: 19 properties = createWelcomeProperties(activity, slotId, viewGroup, platforms); 20 controller = ((WelcomeProperties) properties).getController(); 21 break; 22 default: 23 break; 24 }
上面是我们原先的实现,现在有了这个HashMap后,代码可以这样修改:
Controller controller = creatorMap.get(type);
不仅代码上更加简洁,效率上也提升了,HashMap的查找效率是要比switch-case逐个查询要快的。
当然,如果查询条件多的话,HashMap在设置数据的时候,也是要设置多条数据的,并且HashMap本身也是占用内存的,所以这是典型的用空间换取时间的例子,不过这点内存空间在很多场景下也是可以忽略的。
到底选用哪种方式,取决于我们的业务场景的扩展性,如果考虑到以后我们的业务会增加更多的场景,如果不想修改暴露出去的接口方法,可以采用HashMap的方式,配置对应的类型和策略,但如果这点不计较的话,哪两种其实都是无所谓的。