HTML5技术

重构的那些事儿 - Jun.M(2)

字号+ 作者:H5之家 来源:H5之家 2015-11-18 09:05 我要评论( )

使用反射去掉if/else的原理很简单,使用HashMap建立状态码和需要调用的方法的方法名之间的映射关系,对于每个CountEntry,首先取出状态码,然后根据状态码获得相应的要调用方法的方法名,然后使用java的反射机制就

使用反射去掉if/else的原理很简单,使用HashMap建立状态码和需要调用的方法的方法名之间的映射关系,对于每个CountEntry,首先取出状态码,然后根据状态码获得相应的要调用方法的方法名,然后使用java的反射机制就可以实现对应方法的调用了。本例中使用反射的确可以帮助我们完美的去掉if/else的身影,但是,众所周知,反射效率很低,在高并发的条件下,反射绝对不是一个良好的选择。除去反射这种方法,能想到的就剩下使用策略模式或者与其类似的状态模式,以及工厂模式了,我们以工厂模式为例,经典的架构UML架构图通常由三个组成要素:

策略模式的架构图和工厂模式非常类似,不过在策略模式里执行的对象不叫产品,叫策略。在本例中,这里的产品是虚拟产品,它是服务类性质的接口或者实现。Ok,按照工厂模式的思路重构我们的代码,我们首先定义一个抽象产品接口FillCountService,里面定义产品的行为方法fillCount,代码如下所示:

public interface FillCountService { void fillCount(CountRecoder countRecoder, int count); }

接着我们需要分别实现这六种服务类型的产品,在每种产品中封装不同的服务算法,具体的代码如下所示:

class FirstStageService implements FillCountService { @Override public void fillCount(CountRecoder countRecoder, int count) { countRecoder.setCountOfFirstStage(count); } } class SecondStageService implements FillCountService { @Override public void fillCount(CountRecoder countRecoder, int count) { countRecoder.setCountOfSecondStage(count); } } class ThirdStageService implements FillCountService { @Override public void fillCount(CountRecoder countRecoder, int count) { countRecoder.setCountOfThirdtage(count); } } class ForthStageService implements FillCountService { @Override public void fillCount(CountRecoder countRecoder, int count) { countRecoder.setCountOfForthtage(count); } } class FirthStageService implements FillCountService { @Override public void fillCount(CountRecoder countRecoder, int count) { countRecoder.setCountOfFirthStage(count); } } class SixthStageService implements FillCountService { @Override public void fillCount(CountRecoder countRecoder, int count) { countRecoder.setCountOfSixthStage(count); } }

紧接着,我们需要是实现工厂角色,在工厂内需要实现产品的动态选择算法,使用HashMap维护状态code和具体产品的对象之间的映射关系,
就可以非常容易的实现这一点,具体代码如下所示:

public class FillCountServieFactory { private static Map<Integer, FillCountService> fillCountServiceMap = new HashMap<>(); static { fillCountServiceMap.put(1, new FirstStageService()); fillCountServiceMap.put(2, new SecondStageService()); fillCountServiceMap.put(3, new ThirdStageService()); fillCountServiceMap.put(4, new ForthStageService()); fillCountServiceMap.put(5, new FirthStageService()); fillCountServiceMap.put(6, new SixthStageService()); } public static FillCountService getFillCountStrategy(int statusCode) { return fillCountServiceMap.get(statusCode); } }

客户端在具体使用的时候就变的很简单,那getCountRecoder方法就可以用下面的代码实现:

public CountRecoder getCountRecoder(List<CountEntry> countEntries) { CountRecoder countRecoder = new CountRecoder(); countEntries.stream().forEach(countEntry -> FillCountServieFactory.getFillCountStrategy(countEntry.getCode()) .fillCount(countRecoder, countEntry.getCount())); return countRecoder; } 重构初体验--Java8对模式设计的精简

和反射一样使用设计模式也同样完美的去除了if/else,但是不得不引入大量的具体服务实现类,同时程序中出现大量的模板代码,使得我们程序看起来很不干净,幸好Java 8之后引入了Functional Interface,我们可以使用lambda表达式来去除这些模板代码。将一个接口变为Functional interface,可以通过在接口上添加FunctionalInterface注解实现,代码如下所示:

@FunctionalInterface public interface FillCountService { void fillCount(CountRecoder countRecoder, int count); }

那么具体的服务实现类就可以使用一个简单的lambda表达式代替,原先的FirstStageService类对象就可以使用下面的表达式代替:

(countRecoder, count) -> countRecoder.setCountOfFirstStage(count)

那么工厂类中的代码就可以变为:

public class FillCountServieFactory { private static Map<Integer, FillCountService> fillCountServiceMap = new HashMap<>(); static { fillCountServiceMap.put(1, (countRecoder, count) -> countRecoder.setCountOfFirstStage(count)); fillCountServiceMap.put(2, (countRecoder, count) -> countRecoder.setCountOfSecondStage(count)); fillCountServiceMap.put(3, (countRecoder, count) -> countRecoder.setCountOfThirdtage(count)); fillCountServiceMap.put(4, (countRecoder, count) -> countRecoder.setCountOfForthtage(count)); fillCountServiceMap.put(5, (countRecoder, count) -> countRecoder.setCountOfFirthStage(count)); fillCountServiceMap.put(6, (countRecoder, count) -> countRecoder.setCountOfSixthStage(count)); } public static FillCountService getFillCountStrategy(int statusCode) { return fillCountServiceMap.get(statusCode); } }

这样我们的代码就重构完毕了,当然了还是有些不完美,程序中的魔法数字不利于阅读理解,可以使用易读的常量标识它们,在这里就不做过多说明了。

总结

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 复杂而艰辛的重构之路--起步 - James.Ying

    复杂而艰辛的重构之路--起步 - James.Ying

    2017-04-11 17:05

  • 这些年,我身边的那些人和事 - 左潇龙

    这些年,我身边的那些人和事 - 左潇龙

    2017-02-20 12:01

  • Microsoft Edge与Google Chrome那些不同的举止 - fyter

    Microsoft Edge与Google Chrome那些不同的举止 - fyter

    2017-01-16 12:00

  • sql的那些事(一) - Akon_Coder

    sql的那些事(一) - Akon_Coder

    2017-01-01 12:00

网友点评
t