<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ### Extract Superclass(提煉超類) 兩個classes 有相似特性(similar features)。 為這兩個classes 建立一個superclass ,將相同特性移至superclass 。 ![](https://box.kancloud.cn/2016-08-15_57b1b5e71c4c6.gif) **動機(Motivation)** 重復代碼是系統中最主要的一種糟糕東西。如果你在不同的地方進行相同一件事 情,一旦需要修改那些動作時,你就得負擔比你原本應該負擔的更多事情。 重復代碼的某種形式就是:兩個classes 以相同的方式做類似的事情,或者以不同的方式做類似的事情。對象提供了一種簡化這種情況的機制,那就是繼承機制。但是,在建立這些具有共通性的classes 之前,你往往無法發現這樣的共通性,因此你經常會在「具有共通性」的classes 存在之后,再幵始建立其間的繼承結構。 另一種選擇就是Extract Class。這兩種方案之間的選擇其實就是繼承(Inheritance )和委托(delegation)之間的選擇。如果兩個classes 可以共享行為, 也可以共享接口,那么繼承是比較簡單的作法。如果你選錯了,也總有 Replace Inheritance with Delegation 這瓶后悔藥可吃。 **作法(Mechanics)** - 為原本的classes 新建一個空白的abstract superclass。 - 運用Pull Up Field, Pull Up Method, 和 Pull Up Constructor Body 逐一將subclass 的共同充素上移到superclass 。 - 先搬移值域,通常比較簡單。 - 如果相應的subclass 函數有不同的簽名式(signature),但用途相同,可以先使用Rename Method 將它們的簽名式改為相同,然后 再使用 Pull Up Method。 - 如果相應的subclass 函數有相同的簽名式,但函數本體不同,可以在superclass 中把它們的共同簽名式聲明為抽象函數。 - 如果相應的subclass 函數有不同的函數本體,但用途相同,可試著使用 Substitute Algorithm 把其中一個函數的函數本體拷貝到另一個函數中。如果運轉正常,你就可以使用 Pull Up Method。 - 每次上移后,編譯并測試。 - 檢查留在subclass 中的函數,看它們是否還有共通成分。如果有,可以使用Extract Method 將共通部分再提煉出來,然后使用 Pull Up Method 將提煉出的函數上移到superclass 。如果各個subclass 中某個函數的整體流程很相似,你也許可以使用Form Template Method。 - 將所有共通元素都上移到superclass 之后,檢查subclass 的所有用戶。如果它們只使用共同接口,你就可以把它們所索求的對象型別改為superclass 。 **范例:(Example)** 下面例子中,我以Employee 表示「員工」,以Department 表示「部門」: ~~~ class Employee... public Employee (String name, String id, int annualCost) { _name = name; _id = id; _annualCost = annualCost; } public int getAnnualCost() { return _annualCost; } public String getId(){ return _id; } public String getName() { return _name; } private String _name; private int _annualCost; private String _id; public class Department... public Department (String name) { _name = name; } public int getTotalAnnualCost(){ Enumeration e = getStaff(); int result = 0; while (e.hasMoreElements()) { Employee each = (Employee) e.nextElement(); result += each.getAnnualCost(); } return result; } public int getHeadCount() { return _staff.size(); } public Enumeration getStaff() { return _staff.elements(); } public void addStaff(Employee arg) { _staff.addElement(arg); } public String getName() { return _name; } private String _name; private Vector _staff = new Vector(); ~~~ 這里有兩處共同點。首先,員工和部門都有名稱(names);其次,它們都有年度成本(annual costs),只不過計算方式略有不同。我要提煉出一個superclass ,用以包容這些共通特性。第一步是新建這個superclass ,并將現有的兩個classes 定義為其subclasses: ~~~ abstract class Party {} class Employee extends Party... class Department extends Party... ~~~ 然后我開始把特性上移至superclass 。先實施Pull Up Field 通常會比較簡單: ~~~ class Party... protected String _name; ~~~ 然后,我可以使用 Pull Up Method 把這個值域的取值函數(getter)也上移至superclass : ~~~ class Party { public String getName() { return _name; } ~~~ 我通常會把這個值域聲明為private 。不過,在此之前,我需要先使用Pull Up Constructor Body,這樣才能對_name 正確賦值: ~~~ class Party... protected Party (String name) { _name = name; } private String _name; class Employee... public Employee (String name, String id, int annualCost) { super (name); _id = id; _annualCost = annualCost; } class Department... public Department (String name) { super (name); } ~~~ Department.getTotalAnnualCost() 和 Employee.getAnnualCost() 兩個函數的用途相同,因此它們應該有相同的名稱。我先運用 Rename Method 把它們的名稱改為相同: ~~~ class Department extends Party { public int getAnnualCost(){ Enumeration e = getStaff(); int result = 0; while (e.hasMoreElements()) { Employee each = (Employee) e.nextElement(); result += each.getAnnualCost(); } return result; } ~~~ 它們的函數本體仍然不同,因此我目前還無法使用 Pull Up Method。但是我 可以在superclass 中聲明一個抽象函數: ~~~ abstract public int getAnnualCost() ~~~ 這一步修改完成后,我需要觀察兩個subclasses 的用戶,看看是否可以改變它們轉而使用新的superclass 。用戶之一就是Department 自身,它保存了一個Employee 對象群集。Department .getAnnualCost() 只調用群集內的元素(對象)的getAnnualCost() 函數,而該函數此刻乃是在Party class 聲明的: ~~~ class Department... public int getAnnualCost(){ Enumeration e = getStaff(); int result = 0; while (e.hasMoreElements()) { Party each = (Party) e.nextElement(); result += each.getAnnualCost(); } return result; } ~~~ 這一行為暗示一種新的可能性:我可以用Composite 模式[Gang of Four] 來對待Department 和Employee ,這樣就可以讓一個Department 對象包容另—個Department 對象。這是一項新功能,所以這項修改嚴格來說不屬于重構范圍。如果用戶恰好需要Composite 模式,我可以修改_staff 值域名字,使其更好地表現這一模式。這一修改還會帶來其他相應修改:修改addStaff() 函數名稱,并將該函數的參數型別改為Party class 。最后還需要把headCount() 函數變成一個遞歸調用。我的作法是在Employee 中建立一個headCount() 函數,讓它返回1;再使用Substitute Algorithm 修改Department 的headCount() 函數,讓它總和(add)各部門的headCount() 調用結果。
                  <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>

                              哎呀哎呀视频在线观看