本節書摘來自異步社群《設計模式解析(第2版•修訂版)》一書中的第2章,第2.4節類圖,作者【美】alan shalloway(艾倫•沙洛維) , james r.trott(詹姆斯•r.特羅特),更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
2.4 類圖
設計模式解析(第2版•修訂版)
基本的模組化圖
最基本的uml圖是類圖。它不僅描述了類,而且說明了類之間的關系。這些關系可能有以下這些類型。
當一個類是“一種”另一個類時:is-a(是一種/一個)關系。
當兩個類之間存在關聯時:
一個類“包含”另一個類:has-a(擁有一個)關系;
一個類“使用”另一個類:use-a(使用一個)關系;
一個類“建立”另一類。
這些類型還有一些變體。比如,說“什麼東西包含另一個東西”時,我們可能是指:
被包含者是包含者的一部分(比如汽車中的發動機);
有一個集合,集合中東西可以獨立存在(比如機場上的飛機)。
表示類資訊的不同方法
第一種情況稱為組合(composition),第二種情況稱為聚集(aggrega- tion)1。
圖2-1說明了重要的幾點。首先,矩形表示一個類。在uml中,我可以表示最多三個方面的類的資訊:
類名;
類的資料成員;
類的方法(函數)。

表示類的資訊有三種不同方式。
最左邊的矩形隻顯示了類名。在不需要更詳細資訊時,可以使用類的這種表示形式。
中間的矩形顯示了類名和類的方法。在本例中,square類2有一個display方法。display(方法名)前的加号(+)表示此方法是公開的——也就是說,不屬于此類的其他對象也可以調用。
最右邊的矩形除顯示了前面的資訊(類名和類的方法)之外,還顯示了類的資料成員。在本例中,資料成員length(它是double類型的)前的減号(-)表明這個資料成員的值是私有的,也就是說,除了它所屬的對象外,它對其他對象都是不可見的。3
表示通路權限的uml記号
你可以控制類的資料成員和方法成員的可通路性,也可以用uml标記所需要的每個成員的可通路性。大多數面向對象語言中都有如下三種最常見的可通路性。
公開——用一個加号(+)标記。意味着所有對象都可以通路這個 資料或方法。
保護——用一個“井”号(#)标記。意味着隻有該類及其所有 派生類(包括其派生類的派生類)可以通路這個資料或方法。
私有——用減号()标記。意味着隻有該類的方法可以通路這 個資料或方法。(請注意:某些語言進一步将其限制為特定對象。)
表示關系的uml記号
表示關系的uml記号有如下四種:4
類圖還可以表示關系
類圖還可以表示不同類之間的關系。圖2-2顯示了shape類和它的幾個派生類之間的關系。
表示is-a關系
圖2-2說明了幾件事。首先,shape類下面的箭頭的意思是:指向shape的那些類派生自shape類。而且,shape類的名字是用斜體表示的,說明它是一個抽象類。抽象類就是用來為其派生類定義接口而且存放這些派生類公共資料和方法的類。接口可以看作是沒有公共資料和方法的抽象類——它隻用來作為一種“為要實作它的那些類的方法進行定義”的方式而已。5
表示has-a關系
如前所述,有兩種不同的has-a關系。一個對象可以擁有另一個對象,其中被包含的對象是包含對象的一部分——或者不是。在圖2-3中,我表示出airport“擁有”aircraft。aircraft并不是airport的一部分,但仍然可以說airport擁有aircraft,這種關系稱為聚集。
聚集
在此圖中,我還表示了aircraft要麼是jet(噴射機),要麼是helicopter(直升飛機)。可以看出aircraft類是一個抽象類或者接口6,因為它的名字是用斜體表示的。也就是說,airport可以擁有jet或helicopter,但它是以相同方式對待它們的(當作aircraft)。airport類右邊的空心(未填充的)菱形表示聚集關系。
組合
另一種has-a關系是包含,被包含對象是包含對象的一部分,這種關系也稱為組合。
組合和使用
圖2-4顯示了car(轎車)擁有tire(輪胎),後者是它的一部分(也就是說,car由tire和其他東西組成),這種has-a關系,稱為組合關系(composition),用實心菱形表示。此圖上還顯示了car使用了gasstation(加油站)類,這種使用關系用帶箭頭的虛線表示,也稱依賴關系(dependency relationship)。
組合與聚集的異同
組合和聚集都有“一個對象包含一個或多個對象”的意思,但是,組合意味着“被包含對象是包含對象的一部分”,而聚集意味着被包含對象更像是一個集合。我們可以認為組合是一種非共享的關聯,被包含對象的生存周期由包含對象控制。适當使用構造函數和析構函數在這裡有助于對象的建立和銷毀過程。
uml中的注釋
在圖2-5中有一個新記号:注釋。含有“空心菱形表示聚集”資訊的方框就是注釋。注釋記号看上去好像是右角折起的紙。經常能夠看到注釋通過一條線與特定的類連接配接起來,表示它隻與此類有關。
表示另一個對象所擁有的東西的數量
類圖表示的是類之間的關系,但是,對于組合和聚集來說,這兩種關系更加關注該類型的具體對象。比如,airport對象擁有aircraft對象,但是更具體地說,是特定的機場擁有特定的飛機。于是問題出現了——“一個機場可以擁有多少架飛機呢?”這稱為關系的重數(cardinality)。圖2-6和圖2-7說明了這一點。
重數
圖2-6告訴我們,對于一個airport對象,它可以擁有從0到任意數量(此處用星号表示,但有時候也可以用字母“n”)的aircraft對象。airport類旁的“0..1”意味着:對于一個aircraft對象,它可以被0個或1個airport對象包含。(0表示它可以在空中飛行,不屬于任何機場)。
圖2-7告訴我們,對于一個car對象,它可以擁有4個或5個tire對象(有或沒有備胎),輪胎則隻能裝在一輛轎車上。我曾聽一些人說,如果未指定重數,就意味着隻有一個對象,這種想法是不正确的。如果未指定重數,對于對象的數量不應該做任何假設。
虛線表示依賴
和前面一樣,圖2-7中顯示的car和gasstation之間的虛線表示兩者之間存在依賴。uml用帶虛線的箭頭表示兩個模型元素之間的語義關系(意義)。
1 gamma、helm、johnson和vlissides的《設計模式》一書中将第一種情況稱為“聚集”,而将第二種情況稱為“組合”(《設計模式》一書中aggregation的确相當于本書中的組合概念,但是該書中的composition則是指對象組合,與繼承相對,和本書中的聚集沒有關系。——譯者注)——正好與uml相反。但是,該書完成于uml标準最終定案之前,事實上書中所給出的定義是與uml一緻的。這也說明了開發uml的動機。在uml出現之前已經有好幾種各不相同的模組化語言,每種都有自己的記号和術語。
2類名在文字中引用時,使用courier字型表示。
3在一些程式設計語言中,同類型的對象可以互相共享私有資料。
4原書此段文字與“表示通路權限的uml記号”中的一段文字相同,估計是作者的失誤。——譯者注
5我知道自己兩次使用接口一詞,表示的是不同的含義。但是别為此罵我。我也希望對java和c#的關鍵字——interface使用另一個名字呢。
6為了簡明起見,我不再繼續寫“抽象類或者接口”了。往後我所稱的“抽象類”,均可以視同為“抽象類或者接口”。
本文僅用于學習和交流目的,不代表異步社群觀點。非商業轉載請注明作譯者、出處,并保留本文的原始連結。