<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ### Replace Conditional with Polymorphism(以多態取代條件式) 你手上有個條件式,它根據對象型別的不同而選擇不同的行為。 將這個條件式的每個分支放進一個subclass 內的覆寫函數中,然后將原始函數聲明為抽象函數(abstract method)。 ~~~ double getSpeed() { switch (_type) { case EUROPEAN: return getBaseSpeed(); case AFRICAN: return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts; case NORWEGIAN_BLUE: return (_isNailed) ? 0 : getBaseSpeed(_voltage); } throw new RuntimeException ("Should be unreachable"); } ~~~ ![](https://box.kancloud.cn/2016-08-15_57b1b5aa0c6ab.gif) **動機(Motivation)** 在面向對象術語中,聽上去最高貴的詞非「多態」莫屬。多態(polymorphism)最根本的好處就是:如果你需要根據對象的不同型別而采取不同的行為,多態使你不必編寫明顯的條件式(explicit conditional )。 正因為有了多態,所以你會發現:「針對type code(型別碼)而寫的switch 語句」 以及「針對type string (型別名稱字符串)而寫的if-then-else 語句」在面向對象程序中很少出現。 多態(polymorphism)能夠給你帶來很多好處。如果同一組條件式在程序許多地點出現,那么使用多態的收益是最大的。使用條件式時,如果你想添加一種新型別,就必須查找并更新所有條件式。但如果改用多態,只需建立一個新的subclass ,并在其中提供適當的函數就行了。class 用戶不需要了解這個subclass ,這就大大降低了系統各部分之間的相依程度,使系統升級更加容易。 **作法(Mechanics)** 使用Replace Conditional with Polymorphism之前,你首先必須有一個繼承結構。你可能已經通過先前的重構得到了這一結構。如果還沒有,現在就需要建立它。 要建立繼承結構,你有兩種選擇: Replace Type Code with Subclasses 和 Replace Type Code with State/Strategy。前一種作法比較簡單,因此你應該盡可能使用它。但如果你需要在對象創建好之后修改type code;就不能使用subclassing 作法,只能使用State/Strategy 模式。此,如果由于其他原因你要重構的class 已經有了subclass ,那么也得使用State/Strategy 。記住,如果若干switch 語句針對的是同一個type code;你只需針對這個type code 建立一個繼承結構就行 了。 現在,可以向條件式開戰了。你的目標可能是switch(case)語句,也可能是if 語句。 - 如果要處理的條件式是一個更大函數中的一部分,首先對條件式進行分析,然后使用Extract Method 將它提煉到一個獨立函數去。 - 如果有必要,使用Move Method 將條件式放置到繼承結構的頂端。 - 任選一個subclass ,在其中建立一個函數,使之覆寫superclass 中容納條件式的那個函數。將「與subclass 相關的條件式分支」拷貝到新建函數中,并對它進行適當調整。 - 為了順利進行這一步驟,你可能需要將superclass 中的某些private 值域聲明為protected 。 - 編譯,測試。 - 在superclass 中刪掉條件式內被拷貝出去的分支。 - 編譯,測試。 - 針對條件式的每個分支,重復上述過程,直到所有分支都被移到subclass 內的函數為止。 - 將superclass 之中容納條件式的函數聲明為抽象函數(abstract method)。 **范例:(Example)** 請允許我繼續使用「員工與薪資」這個簡單而又乏味的例子。我的classes是從Replace Type Code with State/Strategy 那個例子中拿來的,因此示意圖就如圖9.1所示(如果想知道這個圖是怎么得到的,請看第8章范例)。 ![](https://box.kancloud.cn/2016-08-15_57b1b5aa20c9a.gif) 圖9.1 繼承機構 ~~~ 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; abstract class EmployeeType... abstract int getTypeCode(); class Engineer extends EmployeeType... int getTypeCode() { return Employee.ENGINEER; } ... and other subclasses ~~~ switch 語句已經被很好地提煉出來,因此我不必費勁再做一遍。不過我需要將它移至EmployeeType class,因為EmployeeType 才是被subclassing 的class 。 ~~~ class EmployeeType... int payAmount(Employee emp) { switch (getTypeCode()) { case ENGINEER: return emp.getMonthlySalary(); case SALESMAN: return emp.getMonthlySalary() + emp.getCommission(); case MANAGER: return emp.getMonthlySalary() + emp.getBonus(); default: throw new RuntimeException("Incorrect Employee"); } } ~~~ 由于我需要EmployeeType class 的數據,所以我需要將Employee 對象作為參數傳遞給payAmount()。這些數據中的一部分也許可以移到EmployeeType class 來,但那是另一項重構需要關心的問題了。 調整代碼,使之通過編譯,然后我修改Employee 中的payAmount() 函數,令它委托(delegate,轉調用)EmployeeType : ~~~ class Employee... int payAmount() { return _type.payAmount(this); } ~~~ 現在,我可以處理switch 語句了。這個過程有點像淘氣小男孩折磨一只昆蟲——每次掰掉它一條腿 [6]。首先我把switch 語句中的"Engineer"這一分支拷貝到Engineer class: ~~~ class Engineer... int payAmount(Employee emp) { return emp.getMonthlySalary(); } ~~~ [6]譯注:「腿」和條件式「分支」的英文都是"leg"。作者幽默地說「掰掉一條腿」, 意思就是「去掉一個分支」。 這個新函數覆寫了superclass 中的switch 語句之內那個專門處理"Engineer"的分支。我是個徧執狂,有時我會故意在case 子句中放一個陷阱,檢查Engineer class 是否正常工作(是否被調用): ~~~ class EmployeeType... int payAmount(Employee emp) { switch (getTypeCode()) { case ENGINEER: throw new RuntimeException ("Should be being overridden"); case SALESMAN: return emp.getMonthlySalary() + emp.getCommission(); case MANAGER: return emp.getMonthlySalary() + emp.getBonus(); default: throw new RuntimeException("Incorrect Employee"); } } ~~~ 接下來,我重復上述過程,直到所有分支都被去除為止: ~~~ class Salesman... int payAmount(Employee emp) { return emp.getMonthlySalary() + emp.getCommission(); } class Manager... int payAmount(Employee emp) { return emp.getMonthlySalary() + emp.getBonus(); } ~~~ 然后,將superclass 的payAmount() 函數聲明為抽象函數: ~~~ class EmployeeType... abstract int payAmount(Employee emp); ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看