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