1. 程式人生 > >java中組合、聚合、關聯

java中組合、聚合、關聯

 類間關係

在類圖中,除了需要描述單獨的類的名稱、屬性和操作外,我們還需要描述類之間的聯絡,因為沒有類是單獨存在的,它們通常需要和別的類協作,創造比單獨工作更大的語義。在UML類圖中,關係用類框之間的連線來表示,連線上和連線端頭處的不同修飾符表示不同的關係。類之間的關係有繼承(泛化)、關聯、聚合和組合。

(1)繼承:指的是一個類(稱為子類)繼承另外的一個類(稱為基類)的功能,並增加它自己的新功能的能力,繼承是類與類之間最常見的關係。類圖中繼承的表示方法是從子類拉出一條閉合的、單鍵頭(或三角形)的實線指向基類。例如,圖3.2給出了MFC中CObject類和選單類CMenu的繼承關係。

     圖3.2 類的繼承

類的繼承在C++中呈現為:

class B { }

 class A : public B{ }

(2)關聯:指的是模型元素之間的一種語義聯絡,是類之間的一種很弱的聯絡。關聯可以有方向,可以是單向關聯,也可以是雙向關聯。可以給關聯加上關聯名來描述關聯的作用。關聯兩端的類也可以以某種角色參與關聯,角色可以具有多重性,表示可以有多少個物件參與關聯。可以通過關聯類進一步描述關聯的屬性、操作以及其他資訊。關聯類通過一條虛線與關聯連線。對於關聯可以加上一些約束,以加強關聯的含義。

 關聯在C++中呈現為:

class A{...}

 class B{ ...}

 A::Function1(B &b) //或A::Function1(B b) //或A::Function1(B *b)

即一個類作為另一個類方法的引數。

(3)聚合:指的是整體與部分的關係。通常在定義一個整體類後,再去分析這個整體類的組成結構。從而找出一些組成類,該整體類和組成類之間就形成了聚合關係。例如一個航母編隊包括海空母艦、驅護艦艇、艦載飛機及核動力攻擊潛艇等。需求描述中“包含”、“組成”、“分為…部分”等詞常意味著聚合關係。

(4)組合:也表示類之間整體和部分的關係,但是組合關係中部分和整體具有統一的生存期。一旦整體物件不存在,部分物件也將不存在。部分物件與整體物件之間具有共生死的關係。

聚合和組合的區別在於:聚合關係是“has-a”關係,組合關係是“contains-a”關係;聚合關係表示整體與部分的關係比較弱,而組合比較強;聚合關係中代表部分事物的物件與代表聚合事物的物件的生存期無關,一旦刪除了聚合物件不一定就刪除了代表部分事物的物件。組合中一旦刪除了組合物件,同時也就刪除了代表部分事物的物件。

我們用淺顯的例子來說明聚合和組合的區別。“國破家亡”,國滅了,家自然也沒有了,“國”和“家”顯然也是組合關係。而相反的,計算機和它的外設之間就是聚合關係,因為它們之間的關係相對鬆散,計算機沒了,外設還可以獨立存在,還可以接在別的計算機上。在聚合關係中,部分可以獨立於聚合而存在,部分的所有權也可以由幾個聚合來共享,比如印表機就可以在辦公室內被廣大同事共用。

在C++語言中,從實現的角度講,聚合可以表示為:

class A {...}

 class B { A* a; .....}

即類B包含類A的指標;

而組合可表示為:

class A{...}

 class B{ A a; ...}

即類B包含類A的物件。

準確的UML類圖中用空心和實心菱形對聚合和組合進行了區分。

          圖3.4 聚合和組合

聚合,關聯,組合 是物件之間的三種關係。從某種意義上說,繼承是一種類的縱向關係,而聚合,關聯,組合是物件的橫向關係。

其關係強弱為 關聯<聚合<組合

關聯和聚合的區別主要在語義上,關聯的兩個物件之間一般是平等的,例如你是我的朋友,聚合則一般不是平等的,例如一個公司包含了很多員工,其實現上是差不多的。聚合和組合的區別則在語義和實現上都有差別,組合的兩個物件之間其生命期有很大的關聯,被組合的物件是在組合物件建立的同時或者建立之後建立,在組合物件銷燬之前銷燬。一般來說被組合物件不能脫離組合物件獨立存在,而且也只能屬於一個組合物件,例如一個文件的版本,必須依賴於文件的存在,也只能屬於一個文件。聚合則不一樣,被聚合的物件可以屬於多個聚合物件,例如一個員工可能可以屬於多個公司。

我想舉個通俗的例子。

你和你的心臟之間是composition關係(心臟只屬於自己)

你和你買的書之間是aggregation關係(書可能是別人的)

你和你的朋友之間是association關係

UML中幾種類間關係:繼承、實現、依賴、關聯、聚合、組合的聯絡與區別

這是一堂關於UML基礎知識的補習課;現在我們做專案時間都太緊了,基本上都沒有做過真正的class級別的詳細設計,更別提使用UML來實現規範建模了;本篇主要就以前自己一直感覺很迷糊的幾種class之間的關係進行整理,讓我們在真正用UML進行比如類圖設計時能夠更加清晰明瞭;以下就分別介紹這幾種關係:

繼承

指的是一個類(稱為子類、子介面)繼承另外的一個類(稱為父類、父介面)的功能,並可以增加它自己的新功能的能力,繼承是類與類或者介面與介面之間最常見的關係;在Java中此類關係通過關鍵字extends明確標識,在設計時一般沒有爭議性;

實現

指的是一個class類實現interface介面(可以是多個)的功能;實現是類與介面之間最常見的關係;在Java中此類關係通過關鍵字implements明確標識,在設計時一般沒有爭議性;

依賴

可以簡單的理解,就是一個類A使用到了另一個類B,而這種使用關係是具有偶然性的、、臨時性的、非常弱的,但是B類的變化會影響到A;比如某人要過河,需要借用一條船,此時人與船之間的關係就是依賴;表現在程式碼層面,為類B作為引數被類A在某個method方法中使用;

關聯

他體現的是兩個類、或者類與介面之間語義級別的一種強依賴關係,比如我和我的朋友;這種關係比依賴更強、不存在依賴關係的偶然性、關係也不是臨時性的,一般是長期性的,而且雙方的關係一般是平等的、關聯可以是單向、雙向的;表現在程式碼層面,為被關聯類B以類屬性的形式出現在關聯類A中,也可能是關聯類A引用了一個型別為被關聯類B的全域性變數;

聚合

聚合是關聯關係的一種特例,他體現的是整體與部分、擁有的關係,即has-a的關係,此時整體與部分之間是可分離的,他們可以具有各自的生命週期,部分可以屬於多個整體物件,也可以為多個整體物件共享;比如計算機與CPU、公司與員工的關係等;表現在程式碼層面,和關聯關係是一致的,只能從語義級別來區分;

組合

組合也是關聯關係的一種特例,他體現的是一種contains-a的關係,這種關係比聚合更強,也稱為強聚合;他同樣體現整體與部分間的關係,但此時整體與部分是不可分的,整體的生命週期結束也就意味著部分的生命週期結束;比如你和你的大腦;表現在程式碼層面,和關聯關係是一致的,只能從語義級別來區分;

對於繼承、實現這兩種關係沒多少疑問,他們體現的是一種類與類、或者類與介面間的縱向關係;其他的四者關係則體現的是類與類、或者類與介面間的引用、橫向關係,是比較難區分的,有很多事物間的關係要想準備定位是很難的,前面也提到,這幾種關係都是語義級別的,所以從程式碼層面並不能完全區分各種關係;但總的來說,後幾種關係所表現的強弱程度依次為:組合>聚合>關聯>依賴;

UML類關係:依賴,關聯,聚合和組合

generalization

2.實現realization.

二、依賴,關聯,聚合和組合

1.例項化(依賴)

A將B作為區域性變數進行使用.

程式1

void A::foo()

{

    B b;

    b.SomeMethod();

}

2.關聯

A與B存在一定的關係. 這裡只考慮單向導航. 關聯在程式碼中有多種表現形式.

第一種, 作為引數:

程式2

void A::foo(B& b) // (B* b) or (B b)

{

    b.SomeMethod();

}

第二種, 作為成員變數:

程式3

class A

{

public:

    A(B& b)

    {

        b_ = b;

    }

    void foo()

    {

        b_.SomeMethod();

    }

private:

    B& b_; // B* b_

};

3.聚合

聚合是一種特殊的關聯, 聚合更明確指出聚合的主體具有整體-部分關係. 程式碼的表現形式見程式3.

4.組合

組合是一種特殊的聚合, 組合中的某個主體控制著另外一個主體的生命週期,而且他們還存在整體-部分關係.

程式4

class A

{

public:

    A()

    {

        b_ = new B;

    }

    ~A()

    {

        delete b_;

        b_ = NULL;

    }

    void foo()

    {

        b_->SomeMethod();

    }

private:

    B* b_;

};

聚合:指的是整體與部分的關係。通常在定義一個整體類後,再去分析這個整體類的組成結構。從而找出一些組成類,該整體類和組成類之間就形成了聚合關係。例如一個航母編隊包括海空母艦、驅護艦艇、艦載飛機及核動力攻擊潛艇等。需求描述中“包含”、“組成”、“分為…部分”等詞常意味著聚合關係。

組合:也表示類之間整體和部分的關係,但是組合關係中部分和整體具有統一的生存期。一旦整體物件不存在,部分物件也將不存在。部分物件與整體物件之間具有共生死的關係。

聚合和組合的區別在於:聚合關係是“has-a”關係,組合關係是“contains-a”關係;聚合關係表示整體與部分的關係比較弱,而組合比較強;聚合關係中代表部分事物的物件與代表聚合事物的物件的生存期無關,一旦刪除了聚合物件不一定就刪除了代表部分事物的物件。組合中一旦刪除了組合物件,同時也就刪除了代表部分事物的物件。

我們用淺顯的例子來說明聚合和組合的區別。“國破家亡”,國滅了,家自然也沒有了,“國”和“家”顯然也是組合關係。而相反的,計算機和它的外設之間就是聚合關係,因為它們之間的關係相對鬆散,計算機沒了,外設還可以獨立存在,還可以接在別的計算機上。在聚合關係中,部分可以獨立於聚合而存在,部分的所有權也可以由幾個聚合來共享,比如印表機就可以在辦公室內被廣大同事共用

關聯和聚合的區別主要在語義上,關聯的兩個物件之間一般是平等的,例如你是我的朋友,聚合則一般不是平等的,例如一個公司包含了很多員工,其實現上是差不多的。聚合和組合的區別則在語義和實現上都有差別,組合的兩個物件之間其生命期有很大的關聯,被組合的物件是在組合物件建立的同時或者建立之後建立,在組合物件銷燬之前銷燬。一般來說被組合物件不能脫離組合物件獨立存在,而且也只能屬於一個組合物件,例如一個文件的版本,必須依賴於文件的存在,也只能屬於一個文件。聚合則不一樣,被聚合的物件可以屬於多個聚合物件,例如一個員工可能可以屬於多個公司。