Change Value to Reference (將值對象改成引用對象)

Summary:

你從一個類衍生出許多彼此相等的實例,但願將它們替換爲同一個對象。將這個值對象變成引用對象。 java

Motivation:

在許多系統中,均可以對對象作一個有用的分類:引用對象和值對象。前者就像「客戶」、「帳戶」這樣的東西,每一個對象都表明真實世界中的一個實物,能夠直接以相等操做符(==)檢查兩個對象是否相等。後者則是像「日期」「錢」這樣的東西,它們徹底由其所含的數據值來定義,你並不在乎副本的存在,系統中或許存在成百上千個內容爲「1/1/2000」的「日期」對象。固然,你也須要知道兩個值對象是否相等,因此須要覆寫equals()(以及hashCode())。 數據庫

要在引用對象和值對象之間作選擇有時並不容易。有時候,你會從一個簡單的值對象開始,在其中保存少許不可修改的數據。然後,可能會但願給這個對象加入一些可修改數據,並確保對任何一個對象的修改都能影響到全部引用此一對象的地方。這時候就須要將這個對象變成一個引用對象。 函數

Mechanics:

1.使用Replace Constructor with Factory Method 測試

2.編譯,測試。 this

3.決定由什麼對象負責提供訪問新對象的途徑。 spa

多是一個靜態字典或一個註冊表對象;也可使用多個對象做爲新對象的訪問點。 code

4.決定這些引用對象應該預先建立好,或是應該動態建立。 對象

若是這些引用對象是預先建立好的,而你必須從內存中將它們讀取出來,那麼就得確保它們在被須要的時候可以被及時加載。 內存

5.修改工廠函數,令它返回引用對象。 ci

若是對象是預先建立好的,就須要考慮:萬一有人索求一個其實並不存在的對象,要如何處理錯誤?

你可能但願對工廠函數使用Rename Method,使其傳達這樣的信息:它返回的是一個既存對象。

6.編譯,測試。

範例

   在Replace Data Value with Object中,咱們留下了一個重構後的程序,此範例就從它開始。

   在上一個重構(Replace Data Value with Object)結束時,Customer對象仍是值對象。就算多份訂單屬於同一個客戶,但每一個Order對象仍是擁有各自的Customer對象。咱們但願改變這一現狀,使得一旦同一個客戶擁有多份不一樣訂單,表明這些訂單的Order對象就能夠共享同一個Customer對象。這就意味着:每個客戶名稱只能對應一個Customer對象。

   首先使用ReplaceConstructor with Factory Method。這樣,就能夠控制Customer對象的建立過程,這在之後是很是重要的。咱們在Customer類中定義這個工廠函數:

public class Customer
{
    public static Customer create( String name )
    {
        return new Customer( name );
    }
}
而後把本來調用構造函數的地方修改成調用工廠函數:
public Order( String customerName )
{
    customer = Customer.create( customerName );
}

而後再把構造函數聲明爲private:

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

如今,咱們必須決定如何訪問Customer對象。能夠經過另個一對象(例如Order中的一個字段)來訪問它。可是本例並無這樣一個明顯的字段可用於訪問Customer對象。在這種狀況下,咱們能夠建立一個註冊表對象來保存全部Customer對象,以此做爲訪問點。爲了簡化咱們的例子,咱們把這個註冊表保存在Customer類的static字段中,讓Customer類做爲訪問點:

private static Dictionary instances = new Hashtable();

而後咱們得決定:應該在接到請求時建立新的Customer對象,仍是應該預先將它們建立好。這裏咱們選擇後者。在應用程序的啓動代碼中,先把須要使用的Customer對象加載穩當。這些對象可能來自數據庫,也可能來自文件。爲求簡單起見,咱們在代碼中明確生成這些對象。若是之後須要,咱們可使用Substitute Algorithem 來改變它們的建立方式。

static void loadCustomers()
{
   new Customer( "Lemon Car Hire" ).store();
   new Customer( "Associated Coffee Machines" ).store();
   new Customer( "Bilston Gasworks" ).store();
}

private void store()
{
    instances.put( this.getName(), this );
}

如今,修改工廠函數,讓它返回預先建立好的Customer對象:

public static Customer create( String name )
{
    return ( Customer ) instances.get( name );
}

因爲create()老是返回既有的Customer對象,因此咱們應該使用Rename Method修改這個工廠函數的名稱,以便強調這一點

public static Customer getNamedCustomer( String name )
 {
     return ( Customer ) instances.get( name );
}
相關文章
相關標籤/搜索