IF多重条件逻辑优化
含义:
- c1:条件1,值为true
- c2:条件2,值为true
- c3:条件3,值为true
事例一:比较简单的if逻辑嵌套
代码抽象:递进式的条件
// 方法开始
...
if (c1) {
if (c2) {
if (c3) {
// 业务逻辑
}
}
}
// 方法结束
优化后的代码逻辑:
// 方法开始
...
if (!c1) {
return;
}
if (!c2) {
return;
}
// 业务逻辑处理
// 方法结束
事例二:复杂场景的if逻辑嵌套
代码抽象:递进式的条件及对应的业务处理
// 方法开始
...
...
if (c1) {
// 业务逻辑一
if (c2) {
// 业务逻辑二
if (c3) {
// 业务逻辑三
}
// 业务逻辑四
}
// 业务逻辑五
}
// 业务逻辑六
// 方法结束
优化后的代码逻辑:
// 业务逻辑抽取独立的方法
m1() {
// 业务逻辑一
}
m2() {
// 业务逻辑二
}
m3() {
// 业务逻辑三
}
m4() {
// 业务逻辑四
}
m5() {
// 业务逻辑五
}
m6() {
// 业务逻辑六
}
// 重构的方法内部开始
...
...
if (!c1) {
m6();
return;
}
m1();
if (!c2) {
m5();
m6();
return;
}
m2();
if (c3) {
m3();
m4();
m5();
m6();
return;
}
m4();
m5();
m6();
// 方法结束
事例三:并列下IF条件逻辑表达式固定的优化
事例:
if (param.equals(val1)) {
doAction1(someParams);
} else if (param.equals(val2)) {
doAction2(someParams);
} else if (param.equals(val3)) {
doAction3(someParams);
}
用表驱动来优化,这个基于表驱动的方式来优化if-else逻辑在Spring中的应用场景很常见,比如NamespaceHandler中注册各种BeanDefinitionParser。Spring的表驱动方式是采用了集中注册的方式,在NamespaceHandlerSupport中。
// 创建值跟动作的映射表
Map<?, Function<?> action> actionMappings = new HashMap<>();
// 存放映射关系
actionMappings.put(val1, (someParams) -> doAction1(someParams));
actionMappings.put(val2, (someParams) -> doAction2(someParams));
actionMappings.put(val3, (someParams) -> doAction3(someParams));
// 获取对应的Funtion,并将someParams入参传到对应的Function中去,省略为null的判断
actionMappings.get(param).apply(someParams);
事例四:if-else中的条件表达式灵活多变
如果if-else中的条件表达式灵活多变,无法进行数据抽象为表格的方式,经常会用责任链设计模式。Spring Web常见的应用是Interceptor机制。
事例五:进行null值判断的if-else条件简化,注解驱动
我们在进行方法传参的时候,经常需要对方法参数作非空判断,可以在方法参数签名中添加@NotNull注解等
事例六:Assert模式【Bean Validation】
事例七:Optional,表示可为空的对象
总结
我们经常不可避免的在代码中写很多的if条件语句,甚至,会形成多重嵌套的if条件结构。掌握IF条件能力,有两点:
- 首先,有递进式的逻辑关系,改成并列式的逻辑关系【取反逻辑】
- 其次,if条件中的业务逻辑处理适当的抽取为独立的方法。
- 在递进式跟并列式的if条件取舍中,还要掌握一个维度,代码简洁。
- if条件个数尽量不要多
- 在事例二中的if(c3)逻辑没有再次取反逻辑,是考虑了这一点,if条件内的是执行几率较少的情况。