使用反射去掉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和具体产品的对象之间的映射关系,
就可以非常容易的实现这一点,具体代码如下所示:
客户端在具体使用的时候就变的很简单,那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); } }这样我们的代码就重构完毕了,当然了还是有些不完美,程序中的魔法数字不利于阅读理解,可以使用易读的常量标识它们,在这里就不做过多说明了。
总结