Replace Delegation with Inheritance (以繼承取代委託)

Summary:你在兩個類之間使用委託關係,並常常爲整個接口編寫許多極簡單的委託函數。讓委託類繼承受託類java

                                               

動機函數

本重構與Replace Inheritance with Delegation 偏偏相反。若是你發現本身須要使用受託類中的全部函數,而且費了很大力氣編寫全部極簡的委託函數,本重構能夠幫助你輕鬆回頭使用繼承。測試

兩條告誡需牢記於心。首先,若是你並無使用受託類的全部函數,那麼就不該該使用Replace Delegation With Inheritance,由於子類應該老是遵循超類的接口。若是過多的委託函數讓你煩心,你有別的選擇:你能夠經過Remove Middle Man 讓客戶端本身調用受託看書,也可使用Extract Superclass 將兩個類接口相同的部分提煉到超類中,而後讓兩個類都繼承這個新的超類;你還能夠用相似的手法使用Extract Interfacespa

另外一種須要小心的狀況是:受託對象被不止一個其餘對象共享,並且受託對象是可變的。在這種狀況下,你就不能將委託關係替換爲繼承關係,由於這樣就沒法再共享數據了。共享數據是必須由委託關係承擔的一種責任,你沒法把它轉給繼承關係。若是受託對象是不可變的,數據共享就不成問題,由於你大可放心地複製對象,誰都不會知道設計

作法code

   1.讓委託端成爲受託端的一個子類對象

   2. 編譯。繼承

注意:此時某些函數可能會發生衝突:它們可能有相同的名稱,但在返回類型、異常指定或可見程度方面有所差別。你可使用Rename Method解決此類問題。遞歸

3.將受託字段設爲該字段所處對象自己。接口

4.去掉簡單的委託函數。

5.編譯並測試。

6.將全部其餘設計委託關係的代碼,改成調用對象自身。

7.移除受託字段

範例:

下面是一個簡單的Employee類,將一些函數委託給另外一個一樣簡單的Person類:

class Employee{
    Person _person = new Person();
    public String getName(){
        return _person.getName();
    }
    
    public void seName(String arg){
        _person.setName(arg);
    }
    
    public String toString(){
        return "Emp:" + _person.getLastName();
    }
}

class Person(){
    String _name;
    public String getName(){
        return _name;
    }
    
    public void setName(String arg){
         _name = arg;
     }
     
     public String getLastName(){
              return _name.subString(_name.lastIndexOf(' ') + 1);
     }
}

第一步,只需聲明二者之間的繼承關係:

class Employee extends Person

此時,若是有任何函數發生衝突,編譯器會提醒咱們。若是某幾個函數的名稱相同,但返回類型不一樣或拋出不一樣的異常,它們之間就會出現衝突。全部此類問題均可以經過Rename Method加以解決。爲求簡化,範例中哦沒有列出這些麻煩的狀況。

下一步要將受託字段設值爲該字段所處對象自身。同時,必須先刪掉全部簡單的委託函數(例如getName()和setName())。若是劉翔這種函數,就會由於無限遞歸而引發系統調用棧溢出。在此範例中,咱們應該把Employee的getName()和setName()拿掉。

一旦Employee能夠正常工做了,就修改其中用到委託函數的代碼,讓它們直接調用從超類繼承而來的函數:

public String toString(){
    return "Emp: " + getLastName();
}

擺脫全部涉及委託關係的函數後,也就能夠擺脫_person這個受託字段了。

相關文章
相關標籤/搜索