求求你,别再写这么多if...else...了
时间:2020-11-09 15:05:28
[导读]if...else 是所有高级编程语言都有的必备功能。但现实中的代码往往存在着过多的 if...else。虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性、可维护性造成很大伤害,进而危害到整个软件系统。现在软件开发领域出现了很多新技术、新概念,但 if...else 这种基本的程序形式并没有发生太大变化。使用好 if...else 不仅对于现在,而且对于将来,都是十分有意义的。今天我们就来看看如何“干掉”代码中的 if...else,还代码以清爽。
前言
问题一:if…else 过多
问题表现
if (condition1) {
} else if (condition2) {
} else if (condition3) {
} else if (condition4) {
} else {
}
通常,if...else 过多的方法,通常可读性和可扩展性都不好。从软件设计角度讲,代码中存在过多的 if...else 往往意味着这段代码违反了违反单一职责原则和开闭原则。因为在实际的项目中,需求往往是不断变化的,新需求也层出不穷。所以,软件系统的扩展性是非常重要的。而解决 if...else 过多问题的最大意义,往往就在于提高代码的可扩展性。
如何解决
接下来我们来看如何解决 if...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);
}
}
注:职责链的控制模式
方法三:注解驱动
介绍
适用场景
实现与示例
方法四:事件驱动
介绍
适用场景
-
表驱动通常是一对一的关系;事件驱动通常是一对多; -
表驱动中,触发和执行通常是强依赖;事件驱动中,触发和执行是弱依赖
实现与示例
方法五:有限状态机
介绍
有限状态机(英语:finite-state machine,缩写:FSM),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
适用场景
实现与示例
方法六:Optional
介绍
使用场景
实现与示例
String str = "Hello World!";
if (str != null) {
System.out.println(str);
} else {
System.out.println("Null");
}
1 Optional strOptional = Optional.of("Hello World!");
2 strOptional.ifPresentOrElse(System.out::println, () -> System.out.println("Null"));
方法七:Assert 模式
介绍
使用场景
扩展: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 表达式过于复杂
问题表现
1 if ((condition1 && condition2 ) || ((condition2 || condition3) && condition4)) {
2
3 }
如何解决
总结
很多芯片都是3.3V供电,有什么科学依据吗?
怎样从零学单片机?
根据时序编程,单片机驱动74HC595实现数码管显示
做了两年硬件后,能否转行到互联网做软件?
免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!





