-描述設計模式的時候會經常用到UML類圖來描述類之間的靜態結構。此篇的用意僅僅在於讓各位看官能夠看懂UML類圖,並且弄清楚UML類圖中的幾種關系。
-在之后的設計模式學習過程中僅此兩點足矣,更高深的不在此篇討論范圍內。
JohnConnor設計模式筆記系列 目錄
JohnConnor設計模式筆記(一) 學習設計模式之前你必須掌握的-看懂UML類圖
JohnConnor設計模式筆記(二) 程序世界里的復印機-原型模式與淺復制/深復制
未完待續......
UML類圖是UML(unified modeling language,標准建模語言)五種圖示法中靜態圖的一種-用來描述系統中類的靜態結構,不僅定義系統中的類,表示類之間的聯系如關聯、依賴、聚合等,也包括類的內部結構(類的屬性和操作)。類圖描述的是一種靜態關系,在系統的整個生命周期都是有效的。
如果諸位看官們有拜讀過一些關於設計模式的動動,就一定有接觸UML類圖,可以說學習類圖是設計模式之旅的起點,下面我們來看一個示例。
一,類的表示
想必電影終結者是深入人心,既然我的英文名與主角同名,那就來個終結者T-800(阿諾肌肉辛格)把。
通常UML類圖中的一個節點就是一個類或者接口。從這個T-800的類我們可以看出,
- 類是由一個三層的矩形組成的:頂部顯示類名,中部顯示特性(屬性或字段等),底部顯示操作(方法或行為)
- 特性的格式是: 可見性修飾符 屬性名:類型 <=默認值>。T-800的特性有型號,目標等。
- 操作的格式是: 可見性修飾符 操作名(<參數列表>):返回類型。操作參數的格式則是<in/out>參數名:類型。in/out來指示參數是輸入還是輸出類型。T-800的操作是重啟。
- 在UML類圖中可見性'+'表示public,'-'表示private,'#'則表示protected。
除了上述例子中可見的UML類圖的規則之外,這里再補充幾點:
- 如果這個類是抽象類,那么類名就必須使用斜體字。
- 如果在一個類圖中我們只想顯示高層細節,那下面的兩個區域的信息不是必要的。
- 操作的參數in/out,除非使用早期的編程語言,這個in/out指示器會有所幫助,一般情況下省略。
二,接口的表示
接口的表示有兩種方式:
矩形表示與類的表示相似,不過需要在接口名稱上方標注<<interface>>,並且接口只有兩個部份,接口名和方法。
棒棒糖表示法,在棒棒糖的名字就是接口的名字,其方法寫在負責實現它的類的操作部份。這里省略了T-800的特性和操作細節。
三,UML類圖中的關系
1.泛化關系(Generalization):使用帶空心三角形的實線表示。
不管是基本款T-800還是液體金屬T-1000,還是最新款的T-X,它們都屬於終結者系列機器人:
泛化關系相當於面向對象中的繼承關系。類T-800,T-1000,T-X都繼承自抽象類(注意類名是斜體)終結者類,則稱終結者類是前三者的一個泛化。
在UML中對泛化關系有三個要求,
- 子類需要繼承父類所有的特性和操作,如上述的三個子類都繼承了父類的型號和目標字段。
- 子類中除了與父類一致的信息外,還應包括額外的信息。比如新的操作:T-800可以重啟(重新設定目標),T-1000可以液化,T-X能控制其他機械。
- 可以使用父類的地方,也可以使用子類。
2.實現關系(Emlpementation):使用帶空心三角形的虛線表示。
在上面的例子中T-800實現了攻擊接口,就引申出了實現關系。
在UML中接口就是一個操作的集合。
3.依賴關系(Dependency):使用帶箭頭的虛線表示。
機器人們依賴於內部的指令來行動。也可以通過指令來重啟T-800來執行其他任務。
依賴是一種最弱的橫向關系。假設A類的變化引起了B類的變化,則稱B依賴於A。表現在代碼上依賴關系一般有如下三種情況:
- A類是B類中(某個方法)的局部變量。
- A類是B類中某個方法的參數。
- A類向B類發送消息,從而影響B類變化。
4.關聯關系(Association):使用實線表示(可帶箭頭)。
從這開始大家可能就會混掉了。不過沒關系,最后會辨析這幾種關系。如果看官們熟悉魔獸世界,兩個一起打22競技場的好基友就是1對1的關聯關系。
如果甲是治療,那這個實線就可以帶箭頭指向乙。因為只需要前者奶好后者,后者只管砍敵人(當然這是很低端的做法吼吼)。
關聯往往是相互的。關聯的兩個對象彼此間沒有任何強制性的約束,可以隨時解除關系或是進行關聯,生命期問題上沒有任何約定。
被關聯的對象還可以再被別的對象關聯,所以關聯是可以共享的。
數字表示了關聯兩者之前的多重性,一般有“*”表示不限,“1”表示有且只有一個,“0...”表示0個或多個,“0,1”表示0個或1個,“m...n”表示m~n個,“m...*”表示至少m個。
5.聚合關系(Aggregation):使用帶空心棱形的實線表示。
聚合關系表示一種弱的整體對部份的擁有關系。主要體現在兩者的生命周期不同,部份可以脫離整體存在。
被聚合的對象還可以再被別的對象關聯,所以被聚合對象是可以共享的。
比如魔獸中的天災軍團,天災們受巫妖王的思想控制,現在小阿被腳男們推倒干掉了天災軍團完蛋了,
旗下的死亡騎士們就追隨黑風騎士團效忠聯盟或者部落,並不意味着他們也就OVER了。
其實聚合也是關聯關系的一個特例。但更緊密,你會跟女朋友親密的分享一切,但不會給一個來串門的朋友配自己家的鑰匙把。
6.組合關系(Composition):使用帶實心棱形的實線表示。
組合關系表示一種強的整體對部份的擁有關系。
在終結者系列電影中,天網是一套擁有了自己意識軍事防御體系的控制程序,控制着麾下的所有機械軍團。
天網系統被摧毀,機械軍團就成了一堆廢銅爛鐵了。(剛才跑題到魔獸世界去了,呃....)
主體控制着部份的創建和銷毀或轉移,部份的生命周期由主體掌握。這就是組合關系。其實也是關聯關系的一種特例。
四,幾種關系的聯系與區別
泛化與實現是兩個縱向關系,這兩者沒什么異議很好區別。
依賴,關聯,聚合,組合這四個橫向關系,由弱到強,區分倒是比較麻煩。
依賴(...use a...) 與其他三者最大的區別在於僅僅是使用,並不持有其依賴對象的引用。代碼的表現就是並不是類的成員之一,而是其方法的參數或局部變量。
聚合(... owns a ...),組合(... is a part of ...),都是關聯(...has a...)的特例。
但關聯更傾向與兩個獨立平等的事物之前的關系,比如好基友,或者好朋友,然而聚合和組合傾向於整體和部份的關系。
聚合和組合的區別,只是在於整體對部份生命周期的把握程度。
聚合就像是電腦壞了的話,硬盤之類的東西是可以繼續用的。組合就像是二極管收音機壞了,那就整個報廢了(對於一般人來說...高手不要吐槽說你會修...)
----------------------------------------------偶是分割線---------------------------------------------------
End:補充一下類圖中的注釋Like this:
最近在學習設計模式,可能的話后面會推出一個系列。我寫的動動一般都是面對跟我一樣的初學者。希望大家到時候捧場吼吼!
以上的圖都是使用MS Visio畫出來的,如果大家感興趣我也可以寫一篇關於使用Visio畫UML類圖的文章^_^。