使用Java8函数式接口去除if/else

原代码:

针对不同的status code,CountRecoder对象会执行不同的set方法,为不同内部属性赋值。

public CountRecoder getCountRecoder(List<CountEntry> countEntries) {
   CountRecoder countRecoder = new CountRecoder();
   for (CountEntry countEntry : countEntries) {
       if (1 == countEntry.getCode()) {
           countRecoder.setCountOfFirstStage(countEntry.getCount());
       } else if (2 == countEntry.getCode()) {
           countRecoder.setCountOfSecondStage(countEntry.getCount());
       } else if (3 == countEntry.getCode()) {
           countRecoder.setCountOfThirdtage(countEntry.getCount());
       } else if (4 == countEntry.getCode()) {
           countRecoder.setCountOfForthtage(countEntry.getCount());
       } else if (5 == countEntry.getCode()) {
           countRecoder.setCountOfFirthStage(countEntry.getCount());
        } else if (6 == countEntry.getCode()) {
            countRecoder.setCountOfSixthStage(countEntry.getCount());
        }
   }
   return countRecoder;
}

CountRecoder对象用于保存一天之中六种状态分别对应的数据条目。CountEntry是对应数据库中每种状态的数据条目记录,包含状态code和以及count两个字段。上面getCountRecoder的方法实现了将list转换为CountRecoder的功能。

重构1 — 反射

使用HashMap建立状态码和需要调用的方法的方法名之间的映射关系,对于每个CountEntry,首先取出状态码,然后根据状态码获得相应的要调用方法的方法名,然后使用java的反射机制就可以实现对应方法的调用了。

private static Map<Integer,String> methodsMap = new HashMap();
static
{
    methodsMap.put(1, "setCountOfFirstStage");
    methodsMap.put(2, "setCountOfSecondStage");
    methodsMap.put(3, "setCountOfThirdtage");
    methodsMap.put(4, "setCountOfForthtage");
    methodsMap.put(5, "setCountOfFirthStage");
    methodsMap.put(6, "setCountOfSixthStage");
}

public CountRecoder getCountRecoderByReflect(List<CountEntry> countEntries) {
    CountRecoder countRecoder = new CountRecoder();
    countEntries.stream().forEach(countEntry -> fillCount(countRecoder, countEntry));
    return countRecoder;
}

private void  fillCount(CountRecoder shippingOrderCountDto, CountEntry countEntry) {
    String name = methodsMap.get(countEntry.getCode());
    Method declaredMethod = null;
    try {
        declaredMethod = CountRecoder.class.getMethod(name, Integer.class);
        declaredMethod.invoke(shippingOrderCountDto, countEntry.getCount());
    } catch (NoSuchMethodException| IllegalAccessException|InvocationTargetException e) {
        System.out.println(e);
    }
}

本例中使用反射的确可以帮助我们完美的去掉if/else的身影,但是,反射效率很低,在高并发的条件下,反射绝对不是一个良好的选择。此外,工厂模式会引入大量的具体服务实现类,同时程序中出现大量的模板代码,使得我们程序看起来很不干净。

重构2 — Java8对模式设计的精简:Functional Interface

Java 8引入了Functional Interface,可以使用lambda表达式来去除工厂模式代码。将一个接口变为Functional interface,可以通过在接口上添加FunctionalInterface注解实现。服务实现类就可以使用一个简单的lambda表达式代替:(countRecoder, count) -> countRecoder.setCountOfFirstStage(count)

@FunctionalInterface
public interface FillCountService {
    void fillCount(CountRecoder countRecoder, int 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);
    }
}

public CountRecoder getCountRecoder(List<CountEntry> countEntries) {
    CountRecoder countRecoder = new CountRecoder();
    countEntries.stream().forEach(countEntry -> 
            FillCountServieFactory.getFillCountStrategy(countEntry.getCode())
                    .fillCount(countRecoder, countEntry.getCount()));
    return countRecoder;
}

【参考】https://www.cnblogs.com/jun-ma/p/4967839.html

你可能感兴趣的:(Java)