1. 程式人生 > >認識UML類關係——依賴、關聯、聚合、組合、泛化

認識UML類關係——依賴、關聯、聚合、組合、泛化

在學習面向物件設計時,類關係涉及依賴、關聯、聚合、組合和泛化這五種關係,耦合度依次遞增。關於耦合度,可以簡單地理解為當一個類發生變更時,對其他類造成的影響程度,影響越小則耦合度越弱,影響越大耦合度越強。

下面根據個人理解,嘗試講解這五種類關係。

1.依賴(Dependency)

依賴關係使用虛線加箭頭表示,如下圖所示:
這裡寫圖片描述

學生在學習生活中經常使用電腦,於是對電腦產生了依賴。依賴關係是五種關係中耦合最小的一種關係。類A要完成某個功能引用了類B,則類A依賴類B。依賴在程式碼中主要體現為類A的某個成員方法的返回值、形參、區域性變數或靜態方法的呼叫,則表示類A引用了類B。以Student類和Computer類為例,用C++語言編碼如下:

class Computer{
public:
    static void start(){
        cout<<"電腦正在啟動"<<endl;
    } 
};
class Student{
public:
    //返回值構成依賴
    Computer& program();
    //形參構成依賴
    void program(Computer&);
    //區域性變數構成依賴
    void playGame(){
        Computer* computer=new Computer;
        ...
    }
    //靜態方法呼叫構成依賴
Computer::star(); };

2.關聯(Association)

關聯關係使用實線加箭頭表示,類之間的關係比依賴要強。學生與老師是關聯的,學生可以不用電腦,但是學生不能沒有老師。如下圖所示:
這裡寫圖片描述

關聯與依賴的對比:
相似之處:
關聯暗示了依賴,二者都用來表示無法用聚合和組合表示的關係。

區別:
(1)發生依賴關係的兩個類都不會增加屬性。其中的一個類作為另一個類的方法的引數或者返回值,或者是某個方法的變數而已。

發生關聯關係的兩個類,類A成為類B的屬性,而屬性是一種更為緊密的耦合,更為長久的持有關係。 在程式碼中的表現如下:

class Teacher
;
class Student{ public: Teacher teacher; //成員變數 void study(); }

(2)從關係的生命週期來看,依賴關係是僅當類的方法被呼叫時而產生,伴隨著方法的結束而結束。關聯關係當類例項化的時候產生,當類物件銷燬的時候關係結束。相比依賴,關聯關係的生存期更長。

關聯關係有單向關聯、雙向關聯、自身關聯、多維關聯等等。其中後三個可以不加箭頭。
單向關聯:
這裡寫圖片描述

雙向關聯:
這裡寫圖片描述

自身關聯:
這裡寫圖片描述

多維關聯:
這裡寫圖片描述

3.聚合(Aggregation)

聚合關係使用實線加空心菱形表示。聚合用來表示集體與個體之間的關聯關係。例如班級與學生之間存在聚合關係,類圖表示如下:
這裡寫圖片描述

聚合關係在程式碼上與關聯關係表現一致,類Student將成為類Classes的成員變數。程式碼如下:

class Student;
class Classes{
public:
    Student* student; 
    Classes(Student* stu):student(stu){}
};

4.組合(複合,Composition)

複合關係使用實線加實心菱形表示。組合又叫複合,用來表示個體與組成部分之間的關聯關係。例如學生與心臟之間存在複合關係,類圖表示如下:
這裡寫圖片描述

組合關係在程式碼上與關聯關係表現一致,類Heart將成為類Student的成員變數。程式碼如下:

class Heart;
class Student{
public:
    Heart* heart; 
    Student(){
        heart=new Heart;
    }
    ~Student(){
        delete heart;
    }
};

聚合與組合的對比:
(1)聚合關係沒有組合緊密。
學生不會因為班級的解散而無法存在,聚合關係的類具有不同的生命週期;而學生如果沒有心臟將無法存活,組合關係的類具有相同的生命週期。

這個從建構函式可以看出。聚合類的建構函式中包含另一個類的例項作為引數,因為建構函式中傳遞另一個類的例項,因此學生可以脫離班級體獨立存在。組合類的建構函式包含另一個類的例項化。因為在建構函式中進行例項化,因此兩者緊密耦合在一起,同生同滅,學生不能脫離心臟而存在。
(2)資訊的封裝性不同。
在聚合關係中,客戶端可以同時瞭解Classes類和Student類,因為他們是獨立的。

在組合關係中,客戶端只認識Student類,根本不知道Heart類的存在,因為心臟類被嚴密地封裝在學生類中。

理解聚合與複合的區別,主要在於聚合的成員可獨立,複合的成員必須依賴於整體才有意義。

5.泛化(Generalization)

泛化是學術名稱,通俗的來講,泛化指的是類與類之間的繼承關係和類與介面之間的實現關係。

繼承關係使用直線加空心三角形表示。類圖結構如下:
這裡寫圖片描述

類介面的實現關係使用虛線加空心三角形表示。類圖結構如下:
這裡寫圖片描述

6.小結

依賴、關聯、聚合、組合與泛化代表類與類之間的耦合度依次遞增。依賴關係實際上是一種比較弱的關聯,聚合是一種比較強的關聯,組合是一種更強的關聯,泛化則是一種最強的關聯,所以籠統的來區分的話,實際上這五種關係都是關聯關係。

依賴關係比較好區分,它是耦合度最弱的一種,在編碼中表現為類成員函式的區域性變數、形參、返回值或對靜態方法的呼叫。

關聯、聚合與組合在編碼形式上都以類成員變數的形式來表示,所以只給出一段程式碼我們很難判斷出是關聯、聚合還是組合關係,我們需要從上下文語境中來判別。關聯表示類之間存在聯絡,不存在集體與個體、個體與組成部分之間的關係。聚合表示類之間存在集體與個體的關係。組合表示個體與組成部分之間的關係。

依賴、關聯、聚合與組合是邏輯上的關聯,泛化是物理上的關聯。物理上的關聯指定是類體的耦合,所以類間耦合性最強。

參考文獻