1、前言
留神题目是过多的,所以三四个就没必要干掉了。理论开发中咱们常常遇到判断条件很多的状况,比方下图有 20 多种状况,不必想必定是要优化代码的,须要思考的是如何去优化?
网上很多说用 switch case 啊,首先不比拟 if else 与 switch case 效率问题的,只从代码整洁度来看二者没啥区别啊!咱们这里更重要的是代码整洁度问题,为什么呢?来看下文的比拟。
2、If else 与 switch case 效率真的差距很大么?
网上有两种见解:
第一种 是说 switch…case 会生成一个跳转表来批示理论的 case 分支的地址,而这个跳转表的索引号与 switch 变量的值是相等的。从而,switch…case 不必像 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 和 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();}
而后春夏秋冬四季流动类实现该接口
@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,后续季度流动调整去批改对应流动策略类中逻辑即可。毛病:如果状况比这多,那么策略类会越来越多,也就是所谓的策略类收缩,并且没有 没有一个中央能够仰视整个业务逻辑。
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);
}
}