干掉过多的 if else,让你的代码更优雅
学习改变命运,技术铸就辉煌。
大家好,我是銘,全栈开发程序员。
写代码时候,有时候条件过多,会有很多 if else ,代码看起来很乱,不够优雅,那如何让代码更优雅呢,如何让代码可读性更强呢,那銘哥就来教你怎么做。
注意啊,是过的 if-else ,如果只是三四个,那就没必要优化了。
写这篇文章之前,我看网上很多说用 switch case 啊,首先不比较 if else 与 switch case 效率问题的,只从代码整洁度来看二者没啥区别啊!我们这里更重要的是代码整洁度问题,为什么呢?来看下文的比较。
If else与switch case效率真的差距很大么?
网上有两种见解:
第一种是说switch…case会生成一个跳转表来指示实际的case分支的地址,而这个跳转表的索引号与switch变量的值是相等的。从而,switch…case不用像if…else那样遍历条件分支直到命中条件,而只需访问对应索引号的表项从而到达定位分支的目的。简单来说就是以空间换时间
第二种是说二者效率上差距并不大
于是銘哥自己去体验一下,不存在复杂业务逻辑,仅仅比较两种方式的效率:
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
策略+工厂模式
上述说到情况较少时并且业务逻辑不复杂的使用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 ,后续季度活动调整去修改对应活动策略类中逻辑即可。缺点:如果情况比这多,那么策略类会越来越多,也就是所谓的策略类膨胀,并且没有一个地方可以俯视整个业务逻辑。
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);
}
}
标签:case,return,dealActivity,干掉,优雅,switch,else,public
From: https://blog.51cto.com/u_16501576/9242845