Java中我如何去除if...else...語句?

2021-03-02 全棧開發者社區

點擊上方[全棧開發者社區]右上角[...][設為星標⭐]

讀牛人技術博客 A Java Geek,最開始覺得這樣的想法很有創意。提前使用靜態代碼塊把對象存入map容器中,在需要的時候在取。他也有提到可以使用DI的方式把需要的對象提前注入好,但是這兩種方式都會造成內存的浪費,因為有一些對象可能是頻繁使用,而有些對象用的概率小甚至一次都沒有用到,那麼這樣的方式是不好的。而且,我們是去除if…else…的語句,這樣的方式雖然好像沒有了if…else…語句,但是本質上並不是最好的方式,只是提供了一種思維方式。

讀《重構 改善既有代碼的設計》有一條就是,以多態取代條件表達式。這是才是最本質的解決方式。

這裡的去除if…else…語句,不是遇見了if…else…語句就去除。這裡是這樣描述的:你手上有個條件表達式,它根據對象類型的不同而選擇不同的行為。而不是平時編寫代碼遇見一些普通的條件表達式就去把它去除,不是這樣的。

而且,一般來說程式語言都有switch語句去替代if…esle…語句。從性能上看這兩個語法也只有非常細微的差別,根本無需關心自己使用了哪個語法。

以多態取代條件表達式

代碼的壞味道一:

double getSpeed() {   switch_ (_type) {     case EUROPEAN:       return getBaseSpeed();     case AFRICAN:       return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts;     case NORWEGIAN_BLUE:       return (is_Nailed) ? 0 : getBaseSpeed(_voltage);   }   throw new RuntimeException("Should be unreachable");}

代碼的壞味道二:

public Foo getFoo(Bar bar) {
if (bar instanceof BarA) { return new FooA(); } else if (bar instanceof BarB) { return new FooB(); } else if (bar instanceof BarC) { return new FooC(); } else if (bar instanceof BarD) { return new FooD(); } throw new BarNotFoundException();}

思路

將這個條件表達式的每個分支放進一個子類內的覆寫函數中,然後將原始函數聲明位抽象函數。

動機(為什麼我們要使用多態取代條件表達式?)

多態最根本的好處就是:如果你需要根據對象的不同類型而採取不同的行為,多態使你不必編寫明顯的條件表達式。

類圖

根據代碼的壞味道一和二以及類圖關係,我們可以得到一個初始版本的代碼

Employee

class Employee...   int payAmount() {     switch (getType()) {       case EmployeeType.ENGINEER:         return _monthlySalary;       case EmployeeType.SALESMAN:         return _monthlySalary + _commission;       case EmployeeType.MANAGER:         return _monthlySalary + _bonus;       default:         throw new RuntimeException("Incorrect Employee");     }   }    int getType() {     return _type.getTypeCode();   }   private EmployeeType _type;

EmployeeType

abstract class EmployeeType...   abstract int getTypeCode();

Engineer

class Engineer extends EmployeeType...  int getTypeCode() {    return Employee.ENGINEER;  }

Manager

class Manager extends EmployeeType...  int getTypeCode() {    return Employee.MANAGER;  }

Salesman

class Salesman extends EmployeeType...  int getTypeCode() {    return Employee.SALESMAN;  }

最終結果代碼布局
Employee

class Employee...   int payAmount() {     return _type.payAmount(this);   }   private EmployeeType _type;

EmployeeType

class EmployeeType...   abstract int payAmount(Employee emp);

Engineer

class Engineer extends EmployeeType...  int payAmount(Employee emp) {    return emp.getMonthlySalary();  }

Manager

calss Manager extends EmployeeType...  int payAmount(Employee emp) {    return emp.getMonthlySalary() + emp.getBouns();  }

Salseman

 class Salseman extends EmployeeType...     int payAmount(Employee emp) {       return emp.getMonthlySalary() + emp.getCommission();     }

理解

a, 把Employee中的原來的屬性_monthlySalary,_commission,_bonus變成最終的採用一個函數獲取。

b, 注意的地方就是誰組合了誰。這裡就是Employee組合了EmployeeType。或者可以理解為誰持有了誰的引用。

c, 其次就是一個繼承關係。

小結

由於偶然讀到別人技術博客關於if…else…的取代文章,發現這也是一個思路,但是不夠那麼好,於是記錄下《重構 改善既有代碼設計》的一個以多態取代條件表達式的範例。

雖然這樣確實處理了if…else…語句,但是一旦使用多態取代條件表達式的方式,必定會引入一個繼承或者實現體系,其實,這是增加了理解的複雜度。

面向對象的編程,如果增加了擴展性必定會引入設計模式,而一旦引入設計模式必定增加理解的複雜度,因為總有繼承體系和實現體系結構,這種結構也是面向對象編程的特色。面向對象編程不一定比面向過程好。在實際的編碼過程中,還是需要權衡這兩種方式。

參與留言集贊送書活動:一個合格的技術面試官是怎麼樣的?(文末送書)

留言打卡27天。

覺得本文對你有幫助?請分享給更多人

關注「全棧開發者社區」加星標,提升全棧技能

本公眾號會不定期給大家發福利,包括送書、學習資源等,敬請期待吧!

如果感覺推送內容不錯,不妨右下角點個在看轉發朋友圈或收藏,感謝支持。

好文章,我在看❤️

相關焦點

  • java基礎案例之java語言流程控制if,if else, if elseif else
    java流程控制語句中判斷結構是由if引導的。;}else{執行語句;}//------------------------重點說下那個if>執行語句;}else if(條件表達式){執行語句;}else{
  • 在 js 開發中,如何減少 if else 語句的使用
    在 js 開發中,如何減少 if else 語句的使用代碼中嵌套的 if/else 結構往往導致代碼不美觀,也不易於理解。
  • 10.Java基礎知識-If語句
    if(關係表達式) {語句體1;}else {語句體2;}執行流程首先判斷關係表達式看其結果是true還是false如果是>/** if語句格式2:* if(關係表達式) {* 語句體1;* }else {* 語句體2;
  • 跟我學java編程—Java簡單條件結構
    在Java語言中,提供了if語句結構來實現條件結構。本節內容只介紹最簡單的條件語句:if語句。>在if-else結構中,如果條件的值為真,則將執行if 後面的語句塊;如果條件的值為假,則將執行else後面的語句塊。
  • 跟我學java編程—Java跳轉語句—continue語句
    continue語句只能用在循環裡。continue語句的作用是跳過循環體中剩餘的語句而準備執行下一次循環。對於while和do-while循環,continue執行之後的動作是條件判斷;對於for循環,隨後的動作是變量更新。
  • 【Java】面試官靈魂拷問:if語句執行完else語句真的不會再執行嗎?
    問題分析最近一名讀者留言說,自己出去面試被面試官的一道奇葩問題問倒了,這個問題就是:if語句執行完else語句真的不會再執行嗎?這名讀者確實不知道該如何回答這個問題。回去後,自己查閱了很多資料也沒弄明白這個問題!想必很多讀者朋友遇到這種奇葩面試題時,多多少少都會覺得鬧心吧!不過,鬧心歸鬧心,問題還是要解決的。今天,我們就一起來剖析下這個奇葩的面試題。
  • VBA中的If-Then-Else語句
    [ elseifstatements ]][ Else[ elsestatements ]]End If各個參數的作用:① condition 必需。② statements 在塊格式中為可選;在沒有Else子句的單行格式中為必需。可以是由冒號分隔的一個或多個語句;在 condition 為 True 時執行。③ condition-n 可選。 與condition相同。④ elseifstatements 可選。 如果關聯condition-n為True, 則執行一個或多個語句。
  • 跟我學java編程—Java跳轉語句—break語句
    有時候,我們需要根據條件跳過循環中的一些語句。Java語言提供了break和continue兩個關鍵字,用於改變程序的控制流。break語句通常用在前面介紹過的switch語句及循環語句中。當break語句用於switch語句時,可使程序跳出switch語句而執行switch語句之後的語句;當break語句用於while、do-while、for循環語句時,可使程序終止循環而執行循環後面的語句。break語句實際上就是為了使人能方便地描述從循環執行中退出的動作。通常應把break語句放在條件語句控制之下,以便在某些條件成立時立即結束循環。
  • while、for、try except語句中的else
    下面要看的是for,while循環和try異常處理語句中的else的用法。一、for,while循環中的elsefor,while循環中,else用於循環正常結束,且循環體中沒有break、return和異常拋出,則執行else語句塊中的內容。例如,我們判斷列表ls中是否全是奇數。普通情況下,需要引入一個標誌變量allOdd,指示所有變量都是奇數,有偶數出現則將此變量設為False。
  • 程式設計師必備 || 學習Java流程控制「條件語句中『if…else語句...
    >if…else語句是條件語句中最常用的以種形式,它會針對某種條件有選擇的做出處理。}else{若干語句}if後面()內的表達式的值必須是boolean型的。如果表達式的值為true,則執行緊跟if語句的複合語句,如果表達式的值為false,則執行else後面的複合語句。同樣簡單的if條件語句一樣,如果if…else語句的語句序列中只有一條語句(不包括注釋),則可以省略該語句序列外面的「{ }」。
  • 聊聊java中一些減少if else的編碼習慣 丨蘆葦技術研習社
    前言前段時間在閱讀別人所寫的代碼的時候 , 發現其中一些業務相關的方法體內 , 出現了比較多的if-else語句多層嵌套的情況 .
  • 跟我學java編程—Java多重if結構
    ,則執行最後一個else後的語句塊;如果沒有最後的else語句,則不執行任何操作,執行該結構後面的語句。同樣,語句塊中包含多條語句時,必須使用「{」和「}」把多條語句括起來。示例1:編寫一個程序,根據用戶輸入的考試成績,輸出相應的成績評定信息。成績大於等於90分輸出「優」;成績大於等於80分小於90分輸出「良」;成績大於等於60分小於80分輸出「中」,成績小於60分輸出「差」。
  • 跟我學java編程—Java嵌套if
    除了使用簡單if和多重if之外,還可以將整個if塊插入另一個if塊中,這種結構稱為嵌套if。嵌套if主要用於只有當前提條件滿足時,才判斷後續條件是否滿足。嵌套if結構的語法如下:在編寫嵌套if結構時,有時會引發一些疑問,下面是一個例子:按條件語句的語法形式,上面的例子似乎有兩種可能的解釋,第一種理解:外層的if是一個沒有else部分的條件語句,最後的else部分屬於內層的if語句;第二種理解:內層if是一個不帶else部分的條件語句
  • 代碼中那麼多「煩人」的if else
    雖然他是偽代碼,並且看起來也很誇張,但在現實中,當我們無數次 Review 別人代碼時,都會發現類似的場景。那麼我們本文就來詳細聊聊,有沒有什麼方法可以讓我們避免來寫這麼多的 if else 呢?我們本文提供了 9 種方法來解決掉那些「煩人」的 if else,一起來看吧。
  • 跟我學java編程—Java條件運算符
    Java語言還提供了一種稱為「條件運算符」的特殊運算符,它可以用於條件表達式中,以提供與if-else等同的結構。此運算符是?和:符號的組合,它是一個三目運算符,即具有三個參與運算的操作數。其語法規則如下:布爾表達式 ?
  • 解鎖Java新姿勢:探討複雜的 if-else 語句「優雅處理」的思路
    毫不誇張的說,我們都寫過類似的代碼,回想起被 if-else 支配的恐懼,我們常常無所下手,甚至不了了之。下面分享一下我在開發中遇到複雜的 if-else 語句「優雅處理」思路。如有不妥,歡迎大家一起交流學習。需求假設有這麼一個需求:一個電商系統,當用戶消費滿1000 金額,可以根據用戶VIP等級,享受打折優惠。
  • C語言if else語句
    如果語句塊中只有一個語句,也可以省略{ },例如:if(age>=18) printf("恭喜,你已經成年,可以使用該軟體!\n");else printf("抱歉,你還未成年,不宜使用該軟體!\n");由於if else 語句可以根據不同的情況執行不同的代碼,所以也叫分支結構或選擇結構,上面的代碼中,就有兩個分支。
  • 跟我學java編程—Java while循環語句
    循環體語句可以是空語句、單條語句或語句集。如果是語句集,則要用「{」和「}」把它們括起來。條件可以是任何表達式。示例1:實現輸出從1—10分別乘以10所得的乘法表。在D盤Java目錄下,新建「LoopSample1.java」文件。
  • R語言決策結構,if語句,if..else語句
    R如果布爾表達式的值為真(true),則if語句中的代碼塊將被執行。如果布爾表達式的計算結果為假(false),則if語句結束後的第一組代碼(在關閉大括號之後)將被執行。R如果布爾表達式求值為真(true),那麼將執行if語句中的代碼塊,否則將執行else語句中的代碼塊。if...else語句的流程圖如下 -
  • 跟我學java編程—深入理解do-while循環語句的用法
    do-while循環與while循環的不同在於:它先執行循環體中的語句,然後再判斷條件是否為真。如果為真則繼續循環,如果為假,則終止循環。因此,do-while循環至少要執行一次循環語句。同樣當有許多語句參加循環時,要用「{」和「}」把它們括起來。