區分關聯、依賴和聚集關係

摘自《Java面向對象編程》一書,作者:孫衛琴 來源:www.javathinker.org

在建立對象模型時,很容易把依賴、關聯和聚集關係混淆。當對象A和對象B之間存在依賴、關聯或聚集關係時,對象A都有可能調用對象B的方法,這是三種關係之間的相同之處,除此之外,它們有着不同的特徵。

1.依賴Dependency關係的特徵


對於兩個相對獨立的系統,當一個系統負責構造另一個系統的實例,或者依賴另一個系統的服務時,這兩個系統之間主要體現爲依賴關係,例如生產零件的機器和零 件,機器負責構造零件對象。再例如充電電池和充電器,充電電池通過充電器來充電。再例如自行車Bicycle和打氣筒Pump,自行車通過打氣筒來充氣。 圖1-39爲Bicycle類與Pump類的類框圖。



圖1-39 Bicycle類與Pump類的依賴關係

Bicycle類和Pump類之間是依賴關係,在Bicycle類中無需定義Pump類型的變量。Bicycle類的定義如下:

public class Bicycle{
/** 給輪胎充氣 */
public void expand(Pump pump){
pump.blow();
}
}


在現時生活中,通常不會爲某一輛自行車配備專門的打氣筒,而是在需要充氣的時候,從附近某個修車棚裏借個打氣筒打氣。在程序代碼中,表現爲Bicycle類的expand()方法有個Pump類型的參數。以下程序代碼表示某輛自行車先後到兩個修車棚裏充氣:

myBicycle.expand(pumpFromRepairShed1); //到第一個修車棚裏充氣
myBicycle.expand(pumpFromRepairShed2); //若干天后,到第二個修車棚裏充氣

2.關聯Association關係的特徵
對於兩個相對獨立的系統,當一個系統的實例與另一個系統的一些特定實例存在固定的對應關係時,這兩個系統之間爲關聯關係。例如客戶和訂單,每個訂單對應特 定的客戶,每個客戶對應一些特定的訂單;再例如公司和員工,每個公司對應一些特定的員工,每個員工對應一特定的公司;再例如自行車和主人,每輛自行車屬於 特定的主人,每個主人有特定的自行車,圖1-40顯示了主人和自行車的關聯關係。而充電電池和充電器之間就不存在固定的對應關係,同樣自行車和打氣筒之間 也不存在固定的對應關係。

圖1-40 主人和自行車的關聯關係


Person類與Bicycle類之間存在關聯關係,這意味着在Person類中需要定義一個Bicycle類型的成員變量。以下是Person類的定義:

public class Person{
private Bicycle bicycle; //主人的自行車

public Bicycle getBicycle(){
return bicycle;
}
public void setBicycle(Bicycle bicycle){
this.bicycle=bicycle;
}
/** 騎自行車去上班 */
public void goToWork(){
bicycle.run();
}
}


在現時生活中,當你騎自行車去上班時,只要從家裏推出自己的自行車就 能上路了,不象給自行車打氣那樣,在需要打氣時,還要四處去找修車棚。因此,在Person類的goToWork()方法中,調用自身的bicycle對 象的run()方法。假如goToWork()方法採用以下的定義方式:

/** 騎自行車去上班 */
public void goToWork(Bicycle bicycle){
bicycle.run();
}

那就好比去上班前,還要先四處去借一輛自行車,然後才能去上班。


3.聚集Aggregatin關係的特徵


當系統A被加入到系統B中,成爲系統B的組成部分時,系統B和系統A之間爲聚集關係。例如自行車和它的響鈴、龍頭、輪胎、鋼圈以及剎車裝置就是聚集關係, 因爲響鈴是自行車的組成部分。而人和自行車不是聚集關係,因爲人不是由自行車組成的,如果一定要研究人的組成,那麼他應該由頭、軀幹和四肢等組成。由此可 見,可以根據語義來區分關聯關係和聚集關係。

聚集關係和關聯關係的區別還表現在以下方面:

(1) 對於具有關聯關係的兩個對象,多數情況下,兩者有獨立的生命週期。比如自行車和他的主人,當自行車不存在了,它的主人依然存在;反之亦然。但在個別情況下,一方會制約另一方的生命週期。比如客戶和訂單,當客戶不存在,它的訂單也就失去存在的意義。

(2) 對於具有聚集關係(尤其是強聚集關係)的兩個對象,整體對象會制約它的組成對象的生命週期。部分類的對象不能單獨存在,它的生命週期依賴於整體類的對象的 生命週期,當整體消失,部分也就隨之消失。比如小王的自行車被偷了,那麼自行車的所有組件也不存在了,除非小王事先碰巧把一些可拆卸的組件(比如車鈴和坐 墊)拆了下來。
不過,在用程序代碼來表示關聯關係和聚集關係時,兩者比較相似。圖1-41爲自行車Bicycle與響鈴Bell的聚集關係。

圖1-41 自行車和響鈴的聚集關係

以下例程1-6是Bicycle類的源程序。

例程1-6 Bicycle.java

public class Bicycle{
private Bell bell;

public Bell getBell(){
return bell;
}

public void setBell(Bell bell){
this.bell=bell;
}

/** 發出鈴聲 */
public void alert(){
bell.ring();
}
}


在Bicycle類中定義了Bell類型的成員變量,Bicycle類利用自身的bell成員變量來發出鈴聲,這和在Person類中定義了Bicycle類型的成員變量,Person類利用自身的bicycle成員變量去上班很相似。

PS:更強的聚集叫做組合(合成)Composition。
可是每本書上面對於聚集和合成的強度認爲是不同的,比如Design Patterns Explained中認爲的
聚集:飛機場和飛機的關係。合成:汽車和輪胎的關係。
《Java面向對象編程》以及Java模式》兩本書中都是把飛機場和飛機的關係認爲是普通關聯,汽車和輪胎的關係認爲是聚集,人和頭的關係認爲是合成。
造成了概念混亂。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章