Move Field (搬移字段)

Summary:  

程序中,某個字段被其所駐類以外的另外一個類更多地用到。在目標類新建一個字段,修改源字段的全部用戶,令它們改用新字段。 java

Motivation: 

 在類之間移動狀態和行爲,是重構過程當中必不可少的措施。隨着系統的發展,你會發現本身須要新的類,並須要將現有工做責任拖到新類中。 函數

對於一個字段,在其所駐類以外的另外一個類中有更多函數使用了它,咱們就能夠考慮搬移這個字段。上述所謂「使用」多是經過設值/取值函數間接進行的。咱們也可能移動該字段的用戶(某個函數),這取決因而否須要保持接口不受變化。若是函數看上去更適合待在原地,那麼就搬移字段。 測試

Mechanics: 

1. 若是字段的訪問級是public,使用 Encapsulate Field將它封裝起來。 this

若是有可能移動移動那些頻繁訪問該字段的函數,或若是有許多函數訪問某個字段,先使用SelfEncapsulate Field也許會有幫助。 spa

2.編譯,測試 rest

3.在目標類中創建與源字段相同的字段,並同時創建相應的設值/取值函數。 code

4. 編譯目標類。 對象

5. 決定如何在源對象中引用目標對象。 接口

可能會有一個現成的字段或函數幫助取得目標對象。若是沒有,就看可否輕鬆創建一個這樣的函數。若是仍是不行,就得在源類中新建一個字段來保存目標對象。這多是一個永久性修改,但也可讓它是暫時的,由於後繼的其餘重構項目可能會把這個新建字段去掉。 get

6. 刪除源字段。

7.將全部對元字段的引用替換爲對某個目標函數的調用。

若是須要讀取該變量,就把對源字段的引用替換爲對目標取值函數的調用;若是要對該變量賦值,就把對源字段的引用替換成對設值函數的調用。

若是源字段不是private的,就必須在源類的全部子類中查找源字段的引用點,並進行相應替換。

           8. 編譯,測試。

範例1

下面是Account類的部分代碼


public class Account
{
    private AccountType type;

    private double interestRate;

    double interestForAmountDays( double amount, int days )
    {
        return interestRate * amount * days / 365;
    }
}
咱們把表示利率的interestRate搬移到AccountType類去。目前已有數個函數引用了它,interestForAmountDays() 就是其一。下一步咱們要在AccountType中創建interestRate字段以及相應的訪問函數:



public class AccountType
{
    private double interestRate;

    public double getInterestRate()
    {
        return interestRate;
    }

    public void setInterestRate( double interestRate )
    {
        this.interestRate = interestRate;
    }
}
這時候,能夠編譯新的AccountType類了。


如今咱們須要讓Account類中訪問interestRate字段的函數轉而是用AccountType對象,而後刪除Account類中的interestRate字段。咱們必須刪除源字段,才能保證其訪問函數的確改變了操做對象,編譯器會幫咱們指出未被正確修改的函數。


public class Account
{
    private AccountType type;

    double interestForAmountDays( double amount, int days )
    {
        return type.getInterestRate() * amount * days / 365;
    }
}

範例2:使用Sel-Encapsulation

若是有不少函數已經使用了interestRate字段,我應該先運用Self-Encapsulate Field(自我封裝)


public class Account
{
    private AccountType type;

    private double interestRate;

    double interestForAmountDays( double amount, int days )
    {
        return getInterestRate() * amount * days / 365;
    }

    private void setInterestRate( double arg )
    {
        interestRate = arg;
    }

    private double getInterestRate()
    {
        return interestRate;
    }
}
這樣,在字段搬移以後,我就只須要修改訪問函數;



public class Account
{
    private AccountType type;

    double interestForAmountDays( double amount, int days )
    {
        return getInterestRate() * amount * days / 365;
    }

    private void setInterestRate( double arg )
    {
        type.setInterestRate( arg );
    }

    private double getInterestRate()
    {
        return type.getInterestRate();
    }
}


之後如有必要,咱們能夠修改訪問函數的用戶,讓它們使用新對象。Self-Encapsulate Field是的咱們得以保持小步前進。若是我須要對類作許多處理,保持小步前進時有幫助的。特別值得一提的是:首先使用Self-Encapsulate Field是咱們得以更輕鬆使用Move Method將函數搬移到目標類中。若是待搬移函數引用了字段的訪問函數,那些引用點是無需修改的。

相關文章
相關標籤/搜索