范例(Examples)
下面是一段簡單程序,其中有兩個(gè)classes:表示[定單]的Order和表示[客戶]的Customer。Order引用了Customer,Customer則并沒有引用Order:
class Order...
Customer getCustomer() {
return _customer;
}
void setCustomer(Customer arg) {
_Customer = arg;
}
Customer _customer; //這是一個(gè)“Order”to “Customer”的連接
首先,我要為Customer添加一個(gè)值域。由于一個(gè)客戶可以擁有多份定單,所以這個(gè)新增值域應(yīng)該是個(gè)群集(collection)。我不希望同一份定單在同一個(gè)群集中出現(xiàn)一次以上,所以這里適合使用set:
class Customer {
private Set _orders = new HashSet();
現(xiàn)在,我需要決定由哪一個(gè)class負(fù)責(zé)控制關(guān)聯(lián)性(association)。我比較喜歡讓單一class來操控,因?yàn)檫@樣我就可以將所有[關(guān)聯(lián)處理邏輯]集中安置于一地。我將按照下列步驟做出這一決定:
但如果這兩個(gè)classes不在同一個(gè)package內(nèi),我就只好把friendOrders()聲明為public了。
class Customer...
Set friendOrders() {
return _orders;
}
現(xiàn)在。我要改變修改函數(shù)(modifier),令它同時(shí)更新反向指針:
class Order...
void setCustomer(Custoemr arg) ...
if(_customer != null) _customer.friendOrders().remove(this);
_customer = arg;
if(_customer != null) _customer.friendOrders().add(this);
}
classes之間的關(guān)聯(lián)性是各式各樣的,因此修改函數(shù)(modifier)的代碼也會(huì)隨之有所差異。如果_customer的值不可能是null,我可 以拿掉上述的第一個(gè)null檢查,但仍然需要檢查引數(shù)(argument)是否是null。不過,基本形式總是相同的:先讓對(duì)方刪除[指向你]的指針,再 將你的指針指向一個(gè)新對(duì)象,最后讓那個(gè)新對(duì)象把它的指針指向你。
如果你希望在Customer中也能修改連接(link),就讓它調(diào)用控制函數(shù):
class Customer ...
void addOrder(Order arg) {
arg.setCustomer(this);
}
如果一份訂單也可以對(duì)應(yīng)多個(gè)客戶,那么你所面臨的就是一個(gè)[多對(duì)多]情況,重構(gòu)后的函數(shù)可能是下面這樣:
class Order ... //controlling methods
void addCustomer(Customer arg) {
arg.friendOrders().add(this);
_customers.add(arg);
}
void removeCustomer(Customer arg) {
arg.friendOrders().remove(this);
_customers.remove(arg);
}
class Customer ...
void addOrder(Order arg) {
arg.addCustomer(this);
}
void removeOrder(Order arg) {
arg.removeCustomer(this);
}
下面是一段簡單程序,其中有兩個(gè)classes:表示[定單]的Order和表示[客戶]的Customer。Order引用了Customer,Customer則并沒有引用Order:
class Order...
Customer getCustomer() {
return _customer;
}
void setCustomer(Customer arg) {
_Customer = arg;
}
Customer _customer; //這是一個(gè)“Order”to “Customer”的連接
首先,我要為Customer添加一個(gè)值域。由于一個(gè)客戶可以擁有多份定單,所以這個(gè)新增值域應(yīng)該是個(gè)群集(collection)。我不希望同一份定單在同一個(gè)群集中出現(xiàn)一次以上,所以這里適合使用set:
class Customer {
private Set _orders = new HashSet();
現(xiàn)在,我需要決定由哪一個(gè)class負(fù)責(zé)控制關(guān)聯(lián)性(association)。我比較喜歡讓單一class來操控,因?yàn)檫@樣我就可以將所有[關(guān)聯(lián)處理邏輯]集中安置于一地。我將按照下列步驟做出這一決定:
- 如果兩者都是reference objects,而其間的關(guān)聯(lián)是[一對(duì)多]關(guān)系,那么就由[擁有單一reference]的那一方承擔(dān)[控制者]角色。以本例而言,如果一個(gè)客戶可擁有多份定單,那么就由Order class(定單)來控制關(guān)聯(lián)性。
- 如果某個(gè)對(duì)象是另一個(gè)對(duì)象的組成(component),那么由后者負(fù)責(zé)控制關(guān)聯(lián)性。
- 如果兩者都是reference objects,而其間的關(guān)聯(lián)是[多對(duì)多]關(guān)系,那么隨便其中哪個(gè)對(duì)象來控制關(guān)聯(lián)性,都無所謂。
但如果這兩個(gè)classes不在同一個(gè)package內(nèi),我就只好把friendOrders()聲明為public了。
class Customer...
Set friendOrders() {
return _orders;
}
現(xiàn)在。我要改變修改函數(shù)(modifier),令它同時(shí)更新反向指針:
class Order...
void setCustomer(Custoemr arg) ...
if(_customer != null) _customer.friendOrders().remove(this);
_customer = arg;
if(_customer != null) _customer.friendOrders().add(this);
}
classes之間的關(guān)聯(lián)性是各式各樣的,因此修改函數(shù)(modifier)的代碼也會(huì)隨之有所差異。如果_customer的值不可能是null,我可 以拿掉上述的第一個(gè)null檢查,但仍然需要檢查引數(shù)(argument)是否是null。不過,基本形式總是相同的:先讓對(duì)方刪除[指向你]的指針,再 將你的指針指向一個(gè)新對(duì)象,最后讓那個(gè)新對(duì)象把它的指針指向你。
如果你希望在Customer中也能修改連接(link),就讓它調(diào)用控制函數(shù):
class Customer ...
void addOrder(Order arg) {
arg.setCustomer(this);
}
如果一份訂單也可以對(duì)應(yīng)多個(gè)客戶,那么你所面臨的就是一個(gè)[多對(duì)多]情況,重構(gòu)后的函數(shù)可能是下面這樣:
class Order ... //controlling methods
void addCustomer(Customer arg) {
arg.friendOrders().add(this);
_customers.add(arg);
}
void removeCustomer(Customer arg) {
arg.friendOrders().remove(this);
_customers.remove(arg);
}
class Customer ...
void addOrder(Order arg) {
arg.addCustomer(this);
}
void removeOrder(Order arg) {
arg.removeCustomer(this);
}