干掉过多的if…else:据说这项技能可以看出程序员的境界!
扫描二维码
随时随地手机看文章
转自:博客园,作者:艾瑞克·邵,www.cnblogs.com/eric-shao/p/10115577.html
serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: 0.544px;text-align: justify;text-indent: 0px;text-transform: none;white-space: normal;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);line-height: 1.5em;">前言
现在软件开发领域出现了很多新技术、新概念,但 if...else 这种基本的程序形式并没有发生太大变化。使用好 if...else 不仅对于现在,而且对于将来,都是十分有意义的。今天我们就来看看如何“干掉”代码中的 if...else,还代码以清爽。
之前嵌入式ARM也曾经重点讲解过这个问题《为什么大量的if else这么不受待见?怎么“干掉”它?》,本篇文章继续深入让你干掉多余的if…else。
▶ 问题一:if…else 过多
问题表现
if (condition1) {
} else if (condition2) {
} else if (condition3) {
} else if (condition4) {
} else {
}
如何解决
-
表驱动 -
职责链模式 -
注解驱动 -
事件驱动 -
有限状态机 -
Optional -
Assert -
多态
方法一:表驱动
介绍
适用场景
实现与示例
if (param.equals(value1)) {
doAction1(someParams);
} else if (param.equals(value2)) {
doAction2(someParams);
} else if (param.equals(value3)) {
doAction3(someParams);
}
// ...
Map<?, Function<?> action> actionMappings = new HashMap<>(); // 这里泛型 ? 是为方便演示,实际可替换为你需要的类型
// When init
actionMappings.put(value1, (someParams) -> { doAction1(someParams)});
actionMappings.put(value2, (someParams) -> { doAction2(someParams)});
actionMappings.put(value3, (someParams) -> { doAction3(someParams)});
// 省略 null 判断
actionMappings.get(param).apply(someParams);
if income <= 2200
tax = 0
else if income <= 2700
tax = 0.14 * (income - 2200)
else if income <= 3200
tax = 70 + 0.15 * (income - 2700)
else if income <= 3700
tax = 145 + 0.16 * (income - 3200)
......
else
tax = 53090 + 0.7 * (income - 102200)
方法二:职责链模式
介绍
适用场景
实现与示例
public void handle(request) {
if (handlerA.canHandle(request)) {
handlerA.handleRequest(request);
} else if (handlerB.canHandle(request)) {
handlerB.handleRequest(request);
} else if (handlerC.canHandle(request)) {
handlerC.handleRequest(request);
}
}
重构后:
public void handle(request) {
handlerA.handleRequest(request);
}
public abstract class Handler {
protected Handler next;
public abstract void handleRequest(Request request);
public void setNext(Handler next) { this.next = next; }
}
public class HandlerA extends Handler {
public void handleRequest(Request request) {
if (canHandle(request)) doHandle(request);
else if (next != null) next.handleRequest(request);
}
}
注:职责链的控制模式
方法三:注解驱动
介绍
适用场景
实现与示例
方法四:事件驱动
介绍
适用场景
-
表驱动通常是一对一的关系;事件驱动通常是一对多; -
表驱动中,触发和执行通常是强依赖;事件驱动中,触发和执行是弱依赖
实现与示例
方法五:有限状态机
介绍
适用场景
实现与示例
-
Apache Mina State Machine
Apache Mina 框架,虽然在 IO 框架领域不及 Netty,但它却提供了一个状态机的功能。https://mina.apache.org/mina-project/userguide/ch14-state-machine/ch14-state-machine.html。有自己实现状态机功能的同学可以参考其源码。 -
Spring State Machine
Spring 子项目众多,其中有个不显山不露水的状态机框架 —— Spring State Machine https://projects.spring.io/spring-statemachine/。可以通过 DSL 和注解两种方式定义。
方法六:Optional
介绍
使用场景
实现与示例
String str = "Hello World!";
if (str != null) {
System.out.println(str);
} else {
System.out.println("Null");
}
Optional<String> strOptional = Optional.of("Hello World!");
strOptional.ifPresentOrElse(System.out::println, () -> System.out.println("Null"));
扩展:Kotlin Null Safety
方法七:Assert 模式
介绍
-
Apache Commons Lang 中的 Validate 类:https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/Validate.html -
Spring 的 Assert 类:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/Assert.html
使用场景
扩展:Bean Validation
方法八:多态
介绍
使用场景
小结
▶ 问题二:if...else 嵌套过深
问题表现
if (condition1) {
action1();
if (condition2) {
action2();
if (condition3) {
action3();
if (condition4) {
action4();
}
}
}
}
如何解决
-
抽取方法 -
卫语句
方法一:抽取方法
介绍
适用场景
实现与示例
public void add(Object element) {
if (!readOnly) {
int newSize = size + 1;
if (newSize > elements.length) {
Object[] newElements = new Object[elements.length + 10];
for (int i = 0; i < size; i++) {
newElements[i] = elements[i];
}
elements = newElements
}
elements[size++] = element;
}
}
重构后:
public void add(Object element) {
if (readOnly) {
return;
}
if (overCapacity()) {
grow();
}
addElement(element);
}
方法二:卫语句
介绍
double getPayAmount() {
double result;
if (_isDead) result = deadAmount();
else {
if (_isSeparated) result = separatedAmount();
else {
if (_isRetired) result = retiredAmount();
else result = normalPayAmount();
};
}
return result;
}
double getPayAmount() {
if (_isDead) return deadAmount();
if (_isSeparated) return separatedAmount();
if (_isRetired) return retiredAmount();
return normalPayAmount();
}
使用场景
▶ 问题三:if...else 表达式过于复杂
问题表现
if ((condition1 && condition2 ) || ((condition2 || condition3) && condition4))
{
...
}
如何解决
总结
-END-
推荐阅读
section>
免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!