1. 程式人生 > >設計模式之UML(一)類圖以及類間關係(泛化 、實現、依賴、關聯、聚合、組合)

設計模式之UML(一)類圖以及類間關係(泛化 、實現、依賴、關聯、聚合、組合)

類圖用於描述系統中所包含的類以及它們之間的相互關係,幫助人們簡化對系統的理解,它是系統分析和設計階段的重要產物,也是系統編碼和測試的重要模型依據。接下來我們就來談談類圖的組成,在下一篇中我們將討論一下類圖之間的關係。

一、類圖的組成

1. 普通類

這裡寫圖片描述

上圖就是一個UML的普通類圖,從上圖我們看出,一個UML通常由三部分組成。

第一部分是類名:每個類都必須有一個名字,類名是一個字串。

第二部分是類的屬性(Attributes):屬性是指類的性質,即類的成員變數。一個類可以有任意多個屬性,也可以沒有屬性。

屬性的格式:

           可見性  名稱:型別 [ = 預設值 ]

其中:
可見性表示該屬性對於類外的元素而言是否可見,包括公有(public)、私有(private)和受保護(protected)三種,在類圖中分別用符號+、-和#表示。

名稱表示屬性名,用一個字串表示。

型別表示屬性的資料型別,可以是基本資料型別,也可以是使用者自定義型別。

預設值是一個可選項,即屬性的初始值。

第三部分是類的操作(Operations):操作是類的任意一個例項物件都可以使用的行為,是類的成員方法。

操作的格式:

            可見性  名稱(引數列表) [ : 返回型別]

其中:
可見性的定義與屬性的可見性定義相同。

名稱即方法名,用一個字串表示。

引數列表表示方法的引數,其語法與屬性的定義相似,引數個數是任意的,多個引數之間用逗號“,”隔開。

返回型別是一個可選項,表示方法的返回值型別,依賴於具體的程式語言,可以是基本資料型別,也可以是使用者自定義型別,還可以是空型別(void),如果是構造方法,則無返回型別。

下劃線表示這個方法是靜態方法。

2. 抽象類

這裡寫圖片描述

就像上圖展示的,抽象類和普通類的區別就是抽象類的名稱是用斜體寫的,並且抽象類中的抽象方法也是斜體的。

3. 介面

這裡寫圖片描述

這裡寫圖片描述

介面有上邊兩種方法,第一種方法是在類的前邊加上<>,這樣這個類就變成了介面類;第二種方法是先宣告一個介面,圓圈旁邊就是介面的名稱,然後與實現它的類聯絡起來,對第二種方法的表示我個人還是不太能理解,圓圈裡並沒有寫這個介面有什麼方法啊,實現它的類中到時有介面的方法,但是又怎麼能區分的出哪些是介面的哪些是本身的呢?還請知道的大神講解一下。

二、類圖中的關係

1. 關聯關係

關聯(Association)關係是類與類之間最常用的一種關係,它是一種結構化關係,用於表示一類物件與另一類物件之間有聯絡,如汽車和輪胎、師傅和徒弟、班級和學生等等。在UML類圖中,用實線連線有關聯關係的物件所對應的類,在使用Java、C#和C++等程式語言實現關聯關係時,通常將一個類的物件作為另一個類的成員變數。在使用類圖表示關聯關係時可以在關聯線上標註角色名,一般使用一個表示兩者之間關係的動詞或者名詞表示角色名(有時該名詞為例項物件名),關係的兩端代表兩種不同的角色,因此在一個關聯關係中可以包含兩個角色名,角色名不是必須的,可以根據需要增加,其目的是使類之間的關係更加明確。

在UML中,關聯關係通常又包含如下幾種形式:

(1) 雙向關聯

預設情況下,關聯是雙向的。例如:顧客(Customer)購買商品(Product)並擁有商品,反之,賣出的商品總有某個顧客與之相關聯。因此,Customer類和Product類之間具有雙向關聯關係,如圖所示:

(2) 單向關聯

類的關聯關係也可以是單向的,單向關聯用帶箭頭的實線表示。例如:顧客(Customer)擁有地址(Address),則Customer類與Address類具有單向關聯關係,如圖所示:

(3) 自關聯

在系統中可能會存在一些類的屬性物件型別為該類本身,這種特殊的關聯關係稱為自關聯。例如:一個節點類(Node)的成員又是節點Node型別的物件,如圖所示:

(4) 多重性關聯

多重性關聯關係又稱為重數性(Multiplicity)關聯關係,表示兩個關聯物件在數量上的對應關係。在UML中,物件之間的多重性可以直接在關聯直線上用一個數字或一個數字範圍表示。

物件之間可以存在多種多重性關聯關係,常見的多重性表示方式如表所示:

表示方式 多重性說明
1..1 表示另一個類的一個物件只與該類的一個物件有關係
0..* 表示另一個類的一個物件與該類的零個或多個物件有關係
1..* 表示另一個類的一個物件與該類的一個或多個物件有關係
0..1 表示另一個類的一個物件沒有或只與該類的一個物件有關係
m..n 表示另一個類的一個物件與該類最少m,最多n個物件有關係 (m≤n)

例如:一個介面(Form)可以擁有零個或多個按鈕(Button),但是一個按鈕只能屬於一個介面,因此,一個Form類的物件可以與零個或多個Button類的物件相關聯,但一個Button類的物件只能與一個Form類的物件關聯,如圖所示

2. 聚合關係

聚合是關聯關係的一種特例,他體現的是整體與部分、擁有的關係,即has-a的關係,此時整體與部分之間是可分離的,他們可以具有各自的生命週期,部分可以屬於多個整體物件,也可以為多個整體物件共享在UML中,聚合關係用帶空心菱形的直線表示。例如:汽車發動機(Engine)是汽車(Car)的組成部分,但是汽車發動機可以獨立存在,因此,汽車和發動機是聚合關係,如圖所示:

在程式碼實現聚合關係時,成員物件通常作為構造方法、Setter方法或業務方法的引數注入到整體物件中。

3.組合關係

組合也是關聯關係的一種特例,他體現的是一種contains-a的關係,這種關係比聚合更強,也稱為強聚合;他同樣體現整體與部分間的關係,但此時整體與部分是不可分的,整體的生命週期結束也就意味著部分的生命週期結束。在UML中,組合關係用帶實心菱形的直線表示。例如:人的頭(Head)與嘴巴(Mouth),嘴巴是頭的組成部分之一,而且如果頭沒了,嘴巴也就沒了,因此頭和嘴巴是組合關係,如圖所示

4.依賴關係

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

在UML中,依賴關係用帶箭頭的虛線表示,由依賴的一方指向被依賴的一方。例如:駕駛員開車,在Driver類的drive()方法中將Car型別的物件car作為一個引數傳遞,以便在drive()方法中能夠呼叫car的move()方法,且駕駛員的drive()方法依賴車的move()方法,因此類Driver依賴類Car,如圖所示:

5.泛化關係

泛化(Generalization)關係也就是繼承關係,用於描述父類與子類之間的關係,父類又稱作基類或超類,子類又稱作派生類。在UML中,泛化關係用帶空心三角形的直線來表示。在程式碼實現時,我們使用面向物件的繼承機制來實現泛化關係,如在Java語言中使用extends關鍵字、在C++/C#中使用冒號“:”來實現。例如:Student類和Teacher類都是Person類的子類,Student類和Teacher類繼承了Person類的屬性和方法,Person類的屬性包含姓名(name)和年齡(age),每一個Student和Teacher也都具有這兩個屬性,另外Student類增加了屬性學號(studentNo),Teacher類增加了屬性教師編號(teacherNo),Person類的方法包括行走move()和說話say(),Student類和Teacher類繼承了這兩個方法,而且Student類還新增方法study(),Teacher類還新增方法teach()。如圖所示:

6.實現關係

介面之間也可以有與類之間關係類似的繼承關係和依賴關係,但是介面和類之間還存在一種實現(Realization)關係,在這種關係中,類實現了介面,類中的操作實現了介面中所宣告的操作。在UML中,類與介面之間的實現關係用帶空心三角形的虛線來表示。例如:定義了一個交通工具介面Vehicle,包含一個抽象操作move(),在類Ship和類Car中都實現了該move()操作,不過具體的實現細節將會不一樣,如圖所示:

三、關係之間的區別

1.聚合與組合

(1)聚合與組合都是一種結合關係,只是額外具有整體-部分的意涵。
(2)部件的生命週期不同
聚合關係中,整件不會擁有部件的生命週期,所以整件刪除時,部件不會被刪除。再者,多個整件可以共享同一個部件。
組合關係中,整件擁有部件的生命週期,所以整件刪除時,部件一定會跟著刪除。而且,多個整件不可以同時間共享同一個部件。
(3)聚合關係是“has-a”關係,組合關係是“contains-a”關係。

2.關聯和聚合

(1)表現在程式碼層面,和關聯關係是一致的,只能從語義級別來區分。
(2)關聯和聚合的區別主要在語義上,關聯的兩個物件之間一般是平等的,例如你是我的朋友,聚合則一般不是平等的。
(3)關聯是一種結構化的關係,指一種物件和另一種物件有聯絡。
(4)關聯和聚合是視問題域而定的,例如在關心汽車的領域裡,輪胎是一定要組合在汽車類中的,因為它離開了汽車就沒有意義了。但是在賣輪胎的店鋪業務裡,就算輪胎離開了汽車,它也是有意義的,這就可以用聚合了。

3.關聯和依賴

(1)關聯關係中,體現的是兩個類、或者類與介面之間語義級別的一種強依賴關係,比如我和我的朋友;這種關係比依賴更強、不存在依賴關係的偶然性、關係也不是臨時性的,一般是長期性的,而且雙方的關係一般是平等的。
(2)依賴關係中,可以簡單的理解,就是一個類A使用到了另一個類B,而這種使用關係是具有偶然性的、臨時性的、非常弱的,但是B類的變化會影響到A。

4.綜合比較

這幾種關係都是語義級別的,所以從程式碼層面並不能完全區分各種關係;但總的來說,後幾種關係所表現的強弱程度依次為:
組合>聚合>關聯>依賴;