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