上期咱們分享了關於Java中equals與hashCode的理解java
本期咱們將分享Java中if/else複雜邏輯的處理git
在github上曾看到一些issue,國外的程序員比較忌諱寫else,看到了不少這樣的評論
else is horrible
,那麼對於邏輯很複雜的代碼段,若是用太多的if/else的話,那麼會致使代碼的閱讀難度變大,同時會增長代碼的圈複雜度
,理論上,若是一個函數的圈複雜度超過8,那麼這個函數就還有可優化的地方,那麼如何優化這種多分支的複雜邏輯的函數呢?手冊中給出了三種方法:衛語句
、策略模式
、狀態模式
,經過閱讀《重構:改善既有代碼的設計》
發現,解決這個問題其實有不少種,下面咱們就一一道來。程序員
這種方法應該是最經常使用的方法之一,當函數過長或者分支太多的話,就能夠考慮將其中的一段代碼提煉成一個獨立的函數。github
public void today() {
if (isBusy()) {
System.out.println("change time.");
} else if (isFree()) {
System.out.println("go to travel.");
} else {
System.out.println("stay at home to learn Alibaba Java Coding Guidelines.");
}
}
複製代碼
public void today() {
if (isBusy()) {
changeTime();
} else if (isFree()) {
goToTravel();
} else {
stayAtHomeToLearn();
}
}
private void changeTime() {
System.out.println("change time.");
}
private void goToTravel() {
System.out.println("go to travel.");
}
private void stayAtHomeToLearn() {
System.out.println("stay at home to learn Alibaba Java Coding Guidelines.");
}
複製代碼
用法:算法
把某個算法替換成另外一個更清晰的算法,或將函數本體替換爲另外一個算法。微信
public String foundPerson(String[] people) {
for (int i = 0; i < people.length; i++) {
if (people[i].equals("Don")) {
return "Don";
}
if (people[i].equals("John")) {
return "John";
}
if (people[i].equals("Kent")) {
return "Kent";
}
}
return "";
}
複製代碼
public String foundPerson(String[] people) {
List<String> candidates = Arrays.asList(new String[] { "Don", "John", "Kent" });
for (int i = 0; i < people.length; i++) {
if (candidates.contains(people[i])) {
return people[i];
}
}
return "";
}
複製代碼
用法:併發
若是有複雜的條件(if-then-else)語句,從if、then、else三個段落中分別提煉出獨立函數。ide
public void today() {
if (isBusy() || isNotWeekend()) {
System.out.println("change time.");
return;
} else {
System.out.println("go to travel.");
}
}
複製代碼
public void today() {
if (notFree()) {
changeTime();
} else {
goToTravel();
}
}
private boolean notFree() {
return isBusy() || isNotWeekend();
}
private void changeTime() {
System.out.println("change time.");
}
private void goToTravel() {
System.out.println("go to travel.");
}
複製代碼
用法:函數
若是有一系列條件測試,都獲得相同結果,將這些測試合併爲一個條件表達式,並將這個條件表達式提煉成爲一個獨立函數。測試
public void today() {
if (isWeekend()) {
System.out.println("go to travel.");
}
if (isHoliday()) {
System.out.println("go to travel.");
}
if (noWork()) {
System.out.println("go to travel.");
}
}
複製代碼
public void today() {
if (isFree()) {
System.out.println("go to travel.");
}
}
private boolean isFree() {
return isWeekend() || isHoliday() || noWork();
}
複製代碼
用法:
在條件表達式的每一個分支上有相同的一段代碼,將這段代碼搬移到條件表達式以外。
public void today() {
if (isBusy()) {
System.out.println("change time.");
sleep();
} else if (isFree()) {
System.out.println("go to travel.");
sleep();
} else {
System.out.println("stay at home to learn Alibaba Java Coding Guidelines.");
sleep();
}
}
複製代碼
public void today() {
if (isBusy()) {
System.out.println("change time.");
} else if (isFree()) {
System.out.println("go to travel.");
} else {
System.out.println("stay at home to learn Alibaba Java Coding Guidelines.");
}
sleep();
}
複製代碼
用法:
在一系列布爾表達式中,某個變量帶有「控制標記(Flag)」的做用,以break語句或者return語句取代控制標記。
若是多個分支都屬於正常行爲,就應該使用if...else...的條件表達式,若是某個條件極其罕見,就應該單獨檢查該條件,並在該條件爲真時馬上從函數中返回,這樣的單獨檢查經常被稱爲衛語句。
public void today() {
if (isBusy()) {
System.out.println("change time.");
} else if (isFree()) {
System.out.println("go to travel.");
} else {
System.out.println("stay at home to learn Alibaba Java Coding Guidelines.");
}
}
複製代碼
public void today() {
if (isBusy()) {
System.out.println("change time.");
return;
}
if (isFree()) {
System.out.println("go to travel.");
return;
}
System.out.println("stay at home to learn Alibaba Java Coding Guidelines.");
return;
}
複製代碼
用法:
合併條件表達式
條件表達式,根據對象的類型選擇不一樣的行爲,將這個條件表達式的每一個分支放進一個子內的覆寫函數中,而後將原始函數聲明爲抽象函數,這一項就是手冊中說的策略模式以及狀態模式。 正由於有了多態,因此「類型碼的switch語句」以及「基於類型名稱的if-then-else」語句在面向對象程序中不多出現。
某個函數既返回對象狀態值,又修改了狀態,創建兩個不一樣的函數,其中一個負責查詢,另外一個負責修改。
若干函數作了相似的工做,但在函數本體中卻包含了不一樣的值,創建單一函數,以參數表達那些不一樣的值。
public void tenPercentRaise() {
salary *= 1.1;
}
public void fivePercentRaise() {
salary *= 1.05;
}
複製代碼
public void raise(double factor) {
salary *= (1 + factor);
}
複製代碼
有一個函數,其中徹底取決於參數值而採起不一樣行爲,針對該參數的每個可能值,創建一個獨立的函數。
public void setValue(String name, int value) {
if (name.equals("height")) {
height = value;
}
if (name.equals("width")) {
width = value;
}
}
複製代碼
public void setHeight(int arg) {
height = arg;
}
public void setWidth(int arg) {
width = arg;
}
複製代碼
用法: