Replace Data Value with Object (以對象取代數據值)

Summary:  

有一個數據項,須要與其餘數據和行爲一塊兒使用纔有意義。將數據項變成對象。 java

Motivation: 

開發初期,咱們以簡單的數據項表示簡單的狀況。可是隨着開發的進行,你可能會發現,這些簡單數據項再也不那麼簡單了。好比說,一開始你可能會用一個字符串來表示「電話號碼」概念,可是隨後就會發現,電話號碼須要「格式化」、「抽取區號」之類的特殊行爲。若是這樣的數據有一兩個,還能夠把相關函數放進數據項所屬的對象裏;可是Duplicate Code壞味道和Feature Envy壞味道很快就會從代碼中散發出來。當這些壞味道開始出現,就應該將數據值變成對象。 函數

Mechanics: 

1.爲帶替換數據新建一個類,在其中聲明一個final字段,其類型和源類中的帶替換數值類型同樣。而後在新類中加入這個字段的取值函數,再加上一個接受此字段爲參數的構造函數。 測試

2.編譯 this

3. 將源類中的帶替換數值字段的類型改成前面新建的類。 spa

4. 修改源類中該字段的取值函數,令它調用新類的取值函數。 code

5. 若是源類構造函數中用到這個待替換字段,咱們就修改構造函數,令它改用新類的構造函數來對字段進行賦值動做。 對象

6.修改源類中待替換字段的設值函數,令它爲新類建立一個實例。 開發

7.編譯,測試 字符串

8. 如今,可能須要對新類使用Change Value to Reference. get

範例

下面有一個表明「訂單」的Order類,其中以一個字符串記錄訂單客戶。如今,咱們但願改用一個對象來表示客戶信息,這樣就有充裕的彈性保存客戶地址、信用等級等信息,也得以安置這些信息的操做行爲。Order類最初以下:

public class Order
{
    private String customer;

    public Order( String customer )
    {
        this.customer = customer;
    }

    public String getCustomer()
    {
        return customer;
    }

    public void setCustomer( String arg )
    {
        customer = arg;
    }
}

使用Order類的代碼可能像下面這樣:

private static int numberOfOrdersFor( Collection orders, String customer )
{
   int result = 0;
   Iterator<Order> iter = orders.iterator();
    while( iter.hasNext() )
    {
        Order each = iter.next();
        if( each.getCustomer().equals( customer ) )
        {
            result++;
         }
     }
    return result;
}

首先,新建一個Customer類表示「客戶」概念。而後在這個類中創建一個final字段,用以保存一個字符串,這是Order類目前所使用的。將這個新字段命名爲name,爲這個字符串加上取值函數和構造函數.

public class Customer
{
    private final String name;

    public Customer( String name )
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }
}
如今,將Order中的customer字段的類型修改成Customer,並修改全部引用該字段的函數,讓它們恰當地改而引用Customer對象。其中取值函數和構造函數的修改都很簡單。至於設值函數,讓它建立一個customer實例。

public class Order
{
    private Customer customer;

    public Order( String customer )
    {
        this.customer = new Customer( customer );
    }

    public String getCustomer()
    {
        return customer.getName();
    }

    public void setCustomer( String arg )
    {
        customer = new Customer( arg );
    }
}
設值函數須要建立一個Customer實例,這是由於之前的字符串是個值對象,因此如今的Customer對象也應該是個值對象。這也就意味着每一個對象都包含本身的一個Customer對象。注意這樣一條規則:值對象應該是不可修改內容的--這即可避免一些討厭的別名問題。

咱們須要觀察Order類中的customer字段的操做函數,並做出一些修改,使它更好地反映出修改後的新形勢。對於取值函數,可使用Rename Method改變名稱,讓它更清晰地表示,它所返回的是消費者名稱,而不是個Customer對象。

public void setCustomerName( String arg )
{
   customer = new Customer( arg );
}
至於構造函數和設值函數,就沒必要修改其簽名了,但參數名稱得改:

public Order( String customerName )
{
   customer = new Customer( customerName );
}
public void setCustomerName( String customerName )
{
   customer = new Customer( customerName );
}
後繼的其餘重構也許會添加「接受現有Customer對象做爲參數」的構造函數和設值函數。
相關文章
相關標籤/搜索