范例(Examples)
在Replace Data Value with Object(175)一節(jié)中,我留下了一個(gè)重構(gòu)后的程序,本節(jié)范例就從它開始。我們有下列的Customer class:
class Customer {
public Customer(String name) {
_name = name;
}
public String getName() {
return _name;
}
private final String _name;
}
它被以下的order class使用:
class Order...
public Order(String customer) {
_customer = new Customer(customer);
}
public String getCustomer() {
return _customer.getName();
}
public void setCustomer(String arg) {
_customer = new Customer(arg);
}
private Customer _customer;
此外,還有一些代碼也會(huì)使用Customer對(duì)象:
private static int numberOfOrdersFor(Collection orders, String customer) {
int result = 0;
Iterator iter = orders.iterator();
while(iter.hasNext()) {
Order each = (Order)iter.next();
if(each.getCustomer().equals(customer)) result ++;
}
return result;
}
到目前為止,Customer對(duì)象還是value object。就算多份定單屬于同一客戶,但每個(gè)order對(duì)象還是擁有各自的Customer對(duì)象。我希望改變這一現(xiàn)狀,使得一旦同一客戶擁有多份不同定單,代表這些定單的所有Order對(duì)象就可以共享同一個(gè)Customer對(duì)象。
首先我使用Replace Constructor with Factory Method(304)。這樣,我就可以控制Customer對(duì)象的創(chuàng)建過程,這在以后會(huì)是非常重要的。我在Customer class中定義這個(gè)factory method:
class Customer {
public static Customer create(String name) {
return new Customer(name);
}
}
然后我把[對(duì)構(gòu)造函數(shù)的調(diào)用]替換成[對(duì)factory method的調(diào)用]:
class Order {
public Order(String customer) {
_customer = Customer.create(customer);
}
}
然后我再把構(gòu)造函數(shù)聲明為private:
class Customer {
private Customer(String name) {
_name = name;
}
}
現(xiàn)在,我必須決定如何訪問Customer對(duì)象。我比較喜歡通過另一個(gè)對(duì)象(例如Order class中的一個(gè)值域)來訪問它。但是本例并沒有這樣一個(gè)明顯的值域可用于訪問Customer對(duì)象。在這種情況下,我通常會(huì)創(chuàng)建一個(gè)注冊(cè)(登錄)對(duì)象,作為訪問點(diǎn)。為了簡(jiǎn)化我們的例子,我把Customer對(duì)象保存在Customer class的一個(gè)static值域中,讓Customer class作為訪問點(diǎn):
private static Dictionary _instance = new Hashtable();
然后我得決定:應(yīng)該在接到請(qǐng)求時(shí)創(chuàng)建新的Customer對(duì)象,還是應(yīng)該預(yù)先將它們創(chuàng)建好。這里我選擇后者。在應(yīng)用程序的啟動(dòng)代碼(start-up code)中,我先把需要使用的Customer對(duì)象加載妥當(dāng)。這些對(duì)象可能來自數(shù)據(jù)庫(kù),也可能來自文件。為求簡(jiǎn)單起見,我在代碼中明確生成這些對(duì)象。反正以后我總是可以使用Substitute Algorithm(139)來改變它們的創(chuàng)建方式。
class Customer...
static void loadCustomers() {
new Customer("Lemon Car Hire").store();
new Customer("Associated Coffee Machines").store();
new Customer("Bilston Gasworks").store();
}
private void store() {
_instance.put(this.getName(), this);
}
現(xiàn)在,我要修改factory method,讓它返回預(yù)先創(chuàng)建好的Customer對(duì)象:
public static Customer create(String name) {
return (Customer)_instance.get(name);
}
由于create()總是返回既有的Customer對(duì)象,所以我應(yīng)該使用Rename Method(273)修改這個(gè)factory method的名稱,以便強(qiáng)調(diào)(說明)這一點(diǎn)。
class Customer...
public static Customer getNamed(String name) {
return (Customer)_instances.get(name);
}
在Replace Data Value with Object(175)一節(jié)中,我留下了一個(gè)重構(gòu)后的程序,本節(jié)范例就從它開始。我們有下列的Customer class:
class Customer {
public Customer(String name) {
_name = name;
}
public String getName() {
return _name;
}
private final String _name;
}
它被以下的order class使用:
class Order...
public Order(String customer) {
_customer = new Customer(customer);
}
public String getCustomer() {
return _customer.getName();
}
public void setCustomer(String arg) {
_customer = new Customer(arg);
}
private Customer _customer;
此外,還有一些代碼也會(huì)使用Customer對(duì)象:
private static int numberOfOrdersFor(Collection orders, String customer) {
int result = 0;
Iterator iter = orders.iterator();
while(iter.hasNext()) {
Order each = (Order)iter.next();
if(each.getCustomer().equals(customer)) result ++;
}
return result;
}
到目前為止,Customer對(duì)象還是value object。就算多份定單屬于同一客戶,但每個(gè)order對(duì)象還是擁有各自的Customer對(duì)象。我希望改變這一現(xiàn)狀,使得一旦同一客戶擁有多份不同定單,代表這些定單的所有Order對(duì)象就可以共享同一個(gè)Customer對(duì)象。
首先我使用Replace Constructor with Factory Method(304)。這樣,我就可以控制Customer對(duì)象的創(chuàng)建過程,這在以后會(huì)是非常重要的。我在Customer class中定義這個(gè)factory method:
class Customer {
public static Customer create(String name) {
return new Customer(name);
}
}
然后我把[對(duì)構(gòu)造函數(shù)的調(diào)用]替換成[對(duì)factory method的調(diào)用]:
class Order {
public Order(String customer) {
_customer = Customer.create(customer);
}
}
然后我再把構(gòu)造函數(shù)聲明為private:
class Customer {
private Customer(String name) {
_name = name;
}
}
現(xiàn)在,我必須決定如何訪問Customer對(duì)象。我比較喜歡通過另一個(gè)對(duì)象(例如Order class中的一個(gè)值域)來訪問它。但是本例并沒有這樣一個(gè)明顯的值域可用于訪問Customer對(duì)象。在這種情況下,我通常會(huì)創(chuàng)建一個(gè)注冊(cè)(登錄)對(duì)象,作為訪問點(diǎn)。為了簡(jiǎn)化我們的例子,我把Customer對(duì)象保存在Customer class的一個(gè)static值域中,讓Customer class作為訪問點(diǎn):
private static Dictionary _instance = new Hashtable();
然后我得決定:應(yīng)該在接到請(qǐng)求時(shí)創(chuàng)建新的Customer對(duì)象,還是應(yīng)該預(yù)先將它們創(chuàng)建好。這里我選擇后者。在應(yīng)用程序的啟動(dòng)代碼(start-up code)中,我先把需要使用的Customer對(duì)象加載妥當(dāng)。這些對(duì)象可能來自數(shù)據(jù)庫(kù),也可能來自文件。為求簡(jiǎn)單起見,我在代碼中明確生成這些對(duì)象。反正以后我總是可以使用Substitute Algorithm(139)來改變它們的創(chuàng)建方式。
class Customer...
static void loadCustomers() {
new Customer("Lemon Car Hire").store();
new Customer("Associated Coffee Machines").store();
new Customer("Bilston Gasworks").store();
}
private void store() {
_instance.put(this.getName(), this);
}
現(xiàn)在,我要修改factory method,讓它返回預(yù)先創(chuàng)建好的Customer對(duì)象:
public static Customer create(String name) {
return (Customer)_instance.get(name);
}
由于create()總是返回既有的Customer對(duì)象,所以我應(yīng)該使用Rename Method(273)修改這個(gè)factory method的名稱,以便強(qiáng)調(diào)(說明)這一點(diǎn)。
class Customer...
public static Customer getNamed(String name) {
return (Customer)_instances.get(name);
}