簡介
類圖是面向對象分析和設計的核心,用來描述系統各個模塊中類與類之間、接口與接口之間、類與接口之間的關系,以及每個類的屬性、操作等特性,一般在詳細設計過程中實施。
類圖本身就是現實世界的抽象,是對系統中各種概念進行建模,並描繪出它們之間的關系,所以類圖關注的對象就是元素及元素之間的關系。
類圖建模步驟
- 抽象出類實體
- 識別出類的主要屬性
- 畫出類之間的關系
- 對各個類進行分析、梳理、設計
類圖的元素
類圖中包含以下幾種模型元素:類、接口、關系、協作、注釋、約束、包。
- 類
在UML的圖形表示中,類的表示法是一個矩形,有三格組成,分別是類名、類屬性、類操作。抽象類中的類名及抽象方法都用斜體表示。
- 類名:首字母大寫
- 類屬性:格式為可見性 屬性名:類型 =默認值,如-name: String
可見性包括四種:
+ public
- private
# protected
* package
屬性名:單字屬性名小寫;多字屬性名出第一個單詞外其余單詞的首字母大寫
- 類操作:格式為可見性 操作名(參數): 返回值類型,如+getName(): String
- 接口
在UML的圖形表示中,接口的表示法是分為兩種:圓形表示法和構造型表示法。
接口由兩欄組成,第一欄頂端是接口名稱,第二欄是接口方法。接口無屬性只包含操作,且沒有對外可見的關聯。
- 圓形表示法
- 構造型表示法
- 關系
類圖中類與類之間有泛化、依賴、關聯、聚合、組合關系;接口與接口之間有繼承關系;類與接口之間有實現關系。這些關系本身就是類圖中的元素,用不同的連線表示。
- 泛化關系
- 依賴關系
- 關聯關系
- 聚合關系
- 組合關系
- 實現關系
類圖中的關系較為復雜,以下分別詳述。
- 協作
協作是指一些類、接口、關系等元素提供的交互行為,能夠協助其他元素執行活動、實現功能的輔助類。
- 注釋
對某些類和接口進行注釋。
- 約束
指定某些類和接口要滿足的一個或多個規則,UML中使用花括號括起來的自由文本標識。
- 包
UML中的包直接對應java中的包,用來表示層次和組織內容。
類圖的關系
類圖中類與類、接口與接口、類與接口之間的關系有四大類:依賴、關聯、泛化、實現,其中關聯有存在聚合、組合兩個特例。
- 依賴
依賴是一種單向使用關系,如果一個類為實現某一功能,使用了其他類作為參數或者調用了其他類的方法,這兩個類之間就產生了依賴關系。
依賴關系表現在在一個類中使用另一個類作為局部變量或者方法參數,以及對另一個類靜態方法的調用。
依賴關系又有五種細分類型:綁定(Binding)依賴、實現(Realization)依賴、使用(Usage)依賴、抽象(Abstraction)依賴、授權(Permission)依賴
綁定依賴
綁定<<bind>>: 以模板參數指定值,生成一個新的模型元素
關鍵字<<bind>>應用於較高級的依賴,用於綁定模板以創建新的模型元素,箭頭指向被綁定的模板
實現依賴
實現<<realize>>:實際上是兩個類/接口之間的契約,也就是說一個類/接口只定義抽象的行為,另一個類定義具體的結構和行為。
使用依賴
使用依賴表示客戶端使用提供者提供的服務幫助實現自身的功能,通常有以下幾種具體應用:
- 使用<<use>>:比較寬泛的概念,表示一個類的行為或實現會影響到另一個類的行為或者實現
- 調用<<call>>:在一個類的方法中調用另一個類的操作
- 參數<<parameter>>:一個類作為另一個類的方法參數
- 發送<<send>>:用一個類中的方法把信號發送到另一個類
- 實例化<<instantiate>>:用一個類的方法創建了另一個類的實例
授權依賴
授權依賴表示一個包/類/元素對另一個包/類/元素進行訪問的權限和能力,包含訪問、導入、友元等依賴關系:
- 訪問<<access>>:允許一個包/類訪問另一個包/類的內容
- 導入<<import>>:允許一個包/類訪問另一個包/類的內容
- 友元<<friend>>: 允許一個元素訪問另一個元素
抽象依賴
抽象依賴表示客戶端與提供者在不同抽象層次上的關系,包括跟蹤、精化、導出等依賴關系:
- 跟蹤<<trace>>:不同模型元素之間的非強相關連接
- 精化<<refine>>:由基本類分解出更明確、更精細的子類
- 導出<<derive>>:一個實例可以從另一個實例導出
- 關聯
關聯是兩個類之間或者類與接口之間的強依賴關系。可以是單向的,也可以是雙向的。
關聯關系一般長期性的、擁有性的關系,而且雙方的關系一般是平等的,如學校與學生之間、老師與學生之間。被關聯類B以類的屬性形式出現在關聯類A中,關聯可以是單向的,也可以是雙向的。
關聯關系在代碼上體現為四種形式:
- 單向關聯:單向擁有關系,只有一個類知道另一個類的屬性和方法
- 雙向關聯:雙向擁有關系,雙方都知道對方的屬性和方法
- 自身關聯:自己關聯自己,這種情況比較少但也有用到,如鏈表
- 多重性關聯:表示兩個類的對象在數量上的對應關系,多重性可在關聯線上用數字范圍表示
multiplicity: 多重性
1 僅為1
* 從0到無窮大
0..1 0 或者 1
n..m [n, m]之間的任何數
UML中使用直線箭頭表示,箭頭指向為被關聯的類,從類A指向類B
單向關聯
雙向關聯
自我關聯
多重性關聯
- 聚合
聚合關系是也是關聯關系的特例。普通關聯關系的兩個類一般處於同一平等層次上,而聚合關系的兩個類處於不同的層次,是整體與部分的關系。聚合關系中的整體和部分是可以分離的,生命周期也是相互獨立的,如公司與員工之間。
UML中使用空心菱形+實線箭頭表示,空心菱形邊指向類School(整體),實現箭頭邊指向部分類Student(部分)
- 組合
組合關系也是關聯關系的特例,屬於強聚合,本身也表示整體與部分的關系,但是組合關系中的整體和部分是不可分離的,整體生命周期的結束時也是部分的生命周期到頭時。如人和大腦。
聚合和組合其實都是關聯的特例,都是整體與部分的關系。它們的區別在於整體和部分是否可分離,聚合的兩個對象之間是可分離的,且具有各自的生命周期,而組合的兩個對象往往表現為一種同命相連的關系。
UML中使用實心菱形+實線箭頭表示,實心菱形邊指向類Person(整體),實線箭頭邊指向類Brain(部分)
- 泛化
泛化指的是子類繼承父類、或子接口繼承父接口的功能並增加自己新功能的過程,是兩個類之間耦合度最大的關系之一。父類稱為基類或超類,子類也稱為派生類。子類可以繼承自抽象類或普通類。
UML中使用實線+空心箭頭表示,箭頭由子類指向父類、或子接口指向父接口
- 實現
實現關系是指一個類實現一個或多個接口功能的過程,這里的接口更多的是一種契約或規范。實現是兩個類之間或類與接口之間耦合度最大的關系之一,在這種關系中,類實現了接口或接口類中所聲明的操作。
UML中使用虛線+空心箭頭表示,箭頭由實現類指向接口
類圖的高級特性
- 抽象類
抽象類是不能直接實例化的類,UML中不論是抽象類名還是抽象方法都是以斜體表示。在不嚴格要求的文檔中也可以普通類加<<abstract>>前綴的方式標識抽象類名和抽象方法。
因為是python設計模式,所以方法名采用了更pythonic的寫法。
標准表示法
構造表示法
- 模板類
UML中引入模板類的目的是應用泛型編程。在類模板聲明的時候根據占位符或參數來定義類,而不用說明屬性、方法參數、方法返回值的實際類型。使用時通過實際值替代占位符或參數即可創建新類/方法/屬性。
python因為是動態語言的原因,所以泛型在python中沒有什么應用場景,以下以Java為例說明模板類的應用。
- 嵌套類
嵌套類是在類中定義的類,相應地把擁有嵌套類的類稱為外部類。嵌套類和外部類之間耦合度更高,並且與外部類更加緊密,在UML中是Composition的另一種表示。
- 主動類
主動類是一種特殊的類,其對象至少擁有一個進程或線程,能夠控制活動中的類。之所以使用主動類是因為開發中需要一些類來控制其他類的運行狀態。
- 關聯類
關聯類既是關聯又是類,它不僅像關聯那樣連接兩個類,而且可以定義一組屬於關聯本身的特性。
類圖注意事項
- 類圖設計初期力求重點突出、簡潔易懂,根據需求變化保持更新
- 類圖中的元素名稱應該直觀、清晰、有意義,不同類的屬性名盡量在全圖中唯一
- 類圖中多個元素之間有依賴關系時需避免循環依賴
- 類圖中類屬性盡量少避免整個圖過於繁雜
- 類圖中可適當使用注釋使系統更清晰易懂
- 對於需求頻繁變化的項目,可多使用草圖進行組內溝通,節省開發和返工時間