文字類別圖


類別

|類別|


繼承

|父類別| => |子類別|

之所以跟 UML 箭頭相反,是因為子類別透過繼承獲得父類別的程式碼,把父類別變成自己的一部分。在「多用合成,少用繼承」的現在,繼承的目的就是獲得程式碼,不是獲得類別的型別,型別都交給介面,所以我採取這更符合現下情況的改變。


介面

/介面/


實作

/介面/ ~ |類別|
/抽象類別/ = |類別|

實作介面一定是單向的,而且介面和類別的符號不同,一看就知道是類別實作介面,所以不需要箭頭。

由於「實作介面」不像「繼承類別」會獲得程式碼,所以另外使用 ~ 符號,不與 = 和 - 符號混淆。

若使用 = 表示會獲得程式碼的「抽象類別」,而不是「介面」。


合成

|主體| <- |部分|
|主體| - /介面/ ~ |實作|

沒有由左往右的順序,顛倒過來沒關係。


成員

|類別 _變數 函式()|
|類別 _變數 _變數 函式() 函式()|
|類別 _變數:型態 函式():傳回值|

現在很少程式設計師用 UML 來塑模,都是用來表達物件之間的關係,所以重點在線條,而不是方框裡面的東西。因此不建議揭露類別裡面的變數和函式,寫類別名稱就好,會讓線條的關係更清楚。

如果變數或函式就是要傳達的關鍵部分,才揭露出來。既然不是塑模,揭露時不要完整,只揭露必要的部分即可。

塑模請用 UML 或 PlantUML,不要用文字類別圖。文字類別圖是彌補語言文字無法描述物件之間關係時用的,請將它視為語言文字的一種,而不是塑模用的一種圖形。

不鼓勵揭露的關係,既然揭露就表示 public,所以不加符號。若要揭露又要表示 private,則標上 _ 符號,但識別名稱已經使用這符號則不加。


綜合範例

/A/ ~ |B| => |C| <- |D| |E| |F|

C 類別繼承了實作 A 介面的 B 類別並合成了 D、E、F 類別。

|A| - /B/ ~ |C| |D| |E|

A 類別透過 B 介面合成實作該介面的 C、D、E 類別。

|C| |D| |E| ~ /B/ - |A|

同上,只是順序不一樣,不影響圖的表示。

|A| - /B/ = |C|

A 類別透過 B 抽象類別相容實作該抽象類別的 C 類別。


應用實例:Monster 設計模式


目的

消除型別。


動機

持續演化(繼承)的一頭怪獸,不受文明(物件導向設計原則)的束縛。


結構

|A| -> |B| -> .. -> |Monster| -> |Client|


參與者

最開始的類別 A,通常選擇 API 裡的一個資料結構來繼承,負責保存資料。

然後類別 B、C、D…負責設計演算法處理類別 A 的資料。每個類別只負責合成一個物件來做事,要合成另一個物件,就繼承一個新的類別去做。

最後的 Monster 負責輸出資料。

Client 端像套用框架一樣繼承 Monster 來用。


實作


123 ABC
444 111 555 333 222
123 ABC


相關模式

類似 God 類別,只是功能並非全寫在一個類別,而是分散在不同類別,然後不斷繼承來用,像隻不停演化的怪獸,擺脫束縛。

最終也不是 new 一個 God 物件,而是繼承 Monster 類別。

God 類別的目的是無所不能的物件,Monster 類別的目的是消除型別。