1、前语

注意标题是过多的,所以三四个就没必要干掉了。实践开发中咱们常常遇到判别条件许多的状况,比方下图有20多种状况,不必想肯定是要优化代码的,需要思考的是如何去优化?

代码优雅之道——如何干掉过多的if else

网上许多说用switch case啊,首先不比较if else与switch case功率问题的,只从代码整齐度来看二者没啥差异啊!咱们这儿更重要的是代码整齐度问题,为什么呢?来看下文的比较。

2、If else与switch case功率真的距离很大么?

网上有两种见解:

第一种是说switch…case会生成一个跳转表来指示实践的case分支的地址,而这个跳转表的索引号与switch变量的值是相等的。然后,switch…case不必像if…else那样遍历条件分支直到命中条件,而只需访问对应索引号的表项然后抵达定位分支的意图。简略来说便是以空间换时刻

第二种是说二者功率上距离并不大

代码优雅之道——如何干掉过多的if else

于是咱们自己去体验一下,不存在杂乱事务逻辑,只是比较两种方法的功率:

    @Test
    void contextLoads() {
        testIf(100000);
        System.gc();
        testSwitch(100000);
    }
    private void testIf(Integer param) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < param; i++) {
            if (i == param-1){
                System.out.println("if判别100000次");
            }
        }
        long end = System.currentTimeMillis();
        long total = end - start;
        System.out.println("Test耗费时刻:" + total);
    }
    private void testSwitch(Integer param){
        long start = System.currentTimeMillis();
        for (int i = 0; i < param; i++) {
            switch (i){
                case 99999:
                    System.out.println("switch判别100000次");
                    break;
            }
        }
        long end = System.currentTimeMillis();
        long total = end - start;
        System.out.println("Test耗费时刻:" + total);
    }

代码优雅之道——如何干掉过多的if else

可见距离并不大。而状况太多的时候谁还会去用if else和switch case呢?下面仍是对两种方法的运用场景做简略的分析:

if else能够把杂乱的逻辑关系表达得明晰、易懂,容纳了程序履行的各种状况。

switch不适合事务系统的实践杂乱需求,事务不断的变更迭代,一更改需求,条件的杂乱度高了,switch无力处理。switch常常忘掉写break,估量许多人一不小心就忘掉写了。switch…case只能处理case为常量的状况。当状况不大于5种并且单一变量的值(如枚举),此时咱们就能够运用switch,它的可读性比if条件更明晰。

除了上述提到枚举的这种场景,主张运用switch,其他个人鄙意:只要状况不大于5种就直接运用if else

3、战略+工厂形式

上述提到状况较少时并且事务逻辑不杂乱的运用if else能够让代码明晰明晰。当每种状况对应的事务逻辑杂乱时,主张运用战略+工厂形式。这儿咱们举个栗子:厂家每个季度要举办不同的活动,咱们运用战略工厂形式来实现

战略接口

public interface Strategy {
    /**
     * 处理各种活动
     * @return
     */
    String dealActivity();
}

然后春夏秋冬四季活动类实现该接口

代码优雅之道——如何干掉过多的if else

@Service
public class SpringActivity implements Strategy{
    @Override
    public String dealActivity() {
        return "春季活动逻辑";
    }
}

战略类工厂

public class StrategyFactory {
    public static Strategy execute(Integer levelCode){
        Strategy strategy = null;
        switch (levelCode){
            case 1:
                strategy = new SpringActivity();
                break;
            case 2:
                strategy = new SummerActivity();
                break;
            case 3:
                strategy = new AutumnActivity();
                break;
            case 4:
                strategy = new WinterActivity();
                break;
            default:
                throw new IllegalArgumentException("活动编号过错");
        }
        return strategy;
    }
}

然后在service层中传入对应的编码即可 ,我这儿省略了service

@RestController
public class TestController {
    @PostMapping("/dealActivity")
    public String dealActivity(Integer code){
        Strategy strategy = StrategyFactory.execute(1);
        return strategy.dealActivity();
    }
}

代码优雅之道——如何干掉过多的if else

上述已经干掉了if else ,后续季度活动调整去修正对应活动战略类中逻辑即可。缺点:如果状况比这多,那么战略类会越来越多,也便是所谓的战略类胀大,并且没有****没有一个当地能够仰望整个事务逻辑。

4、Map+函数式接口

将上述战略类全部作为方法

@Service
public class ActivityStrategyService {
    public String dealSpringActivity(){
        return "春季活动逻辑";
    }
    public String dealSummerActivity() {
        return "夏季活动逻辑";
    }
    public String dealAutumnActivity() {
        return "秋季活动逻辑";
    }
    public String dealWinterActivity() {
        return "冬天活动逻辑";
    }
}

再写个活动Service

@Service
public class ActivityService {
    @Autowired
    private ActivityStrategyService activityStrategyService;
    @FunctionalInterface
    interface ActivityFunction<A>{
        //这儿能够传参啊,我这儿举例用不上参数
        //String dealActivity(A a);
     String dealActivity();
    }
    private final Map<Integer, ActivityFunction> strategyMap = new HashMap<>();
    /**
     * 初始化战略
     */
    @PostConstruct
    public void initDispatcher(){
        strategyMap.put(1,()->activityStrategyService.dealSpringActivity());
        strategyMap.put(2, ()-> activityStrategyService.dealSummerActivity());
        strategyMap.put(3, ()-> activityStrategyService.dealAutumnActivity());
        strategyMap.put(4, ()-> activityStrategyService.dealWinterActivity());
    }
    public String dealActivity(Integer code){
        ActivityFunction<Integer> function = strategyMap.get(code);
        //这儿防止活动编号没匹配上,能够运用断言来判别然后抛出一致异常
        return function.dealActivity();
    }
}

改变Controller

@RestController
public class TestController {
    @Autowired
    private ActivityService activityService;
    @PostMapping("/dealActivity")
    public String dealActivity(Integer code){
//        Strategy strategy = StrategyFactory.execute(1);
//        return strategy.dealActivity();
        return activityService.dealActivity(code);
    }
}