代码简洁之道(lambda+策略工厂模式的初体验)

重构初体验–所谓模式

使用反射去掉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);
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值