重构初体验–所谓模式
使用反射去掉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 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 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)
- 1
那么工厂类中的代码就可以变为:
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);
}
}
这样我们的代码就重构完毕了,当然了还是有些不完美,程序中的魔法数字不利于阅读理解,可以使用易读的常量标识它们,在这里就不做过多说明了。