1、概述
在UML 2.0的13種圖形中,類圖是使用頻率最高的UML圖之一。Martin Fowler在其著作《UML Distilled: A Brief Guide to the Standard Object Modeling Language, Third Edition》(《UML精粹:標(biāo)準(zhǔn)對象建模語言簡明指南(第3版)》)中有這么一段:“If someone were to come up to you in a dark alley and say, 'Psst, wanna see a UML diagram?' that diagram would probably be a class diagram. The majority of UML diagrams I see are class diagrams.”(“如果有人在黑暗的小巷中向你走來并對你說:‘嘿,想不想看一張UML圖?’那么這張圖很有可能就是一張類圖,我所見過的大部分的UML圖都是類圖”),由此可見類圖的重要性。
==類圖==用于描述系統(tǒng)中所包含的類以及它們之間的相互關(guān)系,幫助人們簡化對系統(tǒng)的理解,它是==系統(tǒng)分析和設(shè)計階段的重要產(chǎn)物,也是系統(tǒng)編碼和測試的重要模型依據(jù)==。
==類圖(Class Diagram)==使用出現(xiàn)在系統(tǒng)中的不同類來描述系統(tǒng)的靜態(tài)結(jié)構(gòu),它用來描述不同的類以及它們之間的關(guān)系。
2、類圖的元素
在類圖中一共包含了以下幾種模型元素,分別是:類(Class)、接口(Interface)、依賴(Dependency)關(guān)系、泛化(Generalization)關(guān)系、關(guān)聯(lián)(Association)關(guān)系、聚合關(guān)系(Aggregation)、組合關(guān)系(Composition)和實現(xiàn)(Realization)關(guān)系。本節(jié)介紹類、接口,下一節(jié)具體介紹各種關(guān)系。
2.1 類
在面向?qū)ο螅∣O) 編程中,類是對現(xiàn)實世界中一組具有相同特征的物體的抽象。包括名稱、屬性和操作。

2.2 接口
接口是一種特殊的類,具有類的結(jié)構(gòu)但不可被實例化,只可以被實現(xiàn)(繼承)。在UML中,接口使用一個帶有名稱的小圓圈來進行表示。也可以說,是在沒有給出對象的實現(xiàn)和狀態(tài)的情況下對對象行為的描述。
與類圖不同,是頂部有一個《interface》顯示:

也可以是一個空心圓表示:

3、類的關(guān)系
在UML類圖中,常見的有以下幾種關(guān)系: 泛化(Generalization), 實現(xiàn)(Realization),關(guān)聯(lián)(Association),聚合(Aggregation),組合(Composition),依賴(Dependency)。
各種關(guān)系的強弱順序:
泛化 = 實現(xiàn) > 組合 > 聚合 > 關(guān)聯(lián) > 依賴
3.1 泛化(Generalization)
【泛化關(guān)系】:是一種繼承關(guān)系,表示一般與特殊的關(guān)系,它指定了子類如何特化父類的所有特征和行為。例如:老虎是動物的一種,即有老虎的特性也有動物的共性。
【箭頭指向】:帶三角箭頭的實線,箭頭指向父類
【java表示方法】:==extends==
【類的種類】:都可以

3.2 實現(xiàn)(Realization)
【實現(xiàn)關(guān)系】:是一種類與接口的關(guān)系,表示類是接口所有特征和行為的實現(xiàn).
【箭頭指向】:帶三角箭頭的虛線,箭頭指向接口
【java表示方法】:==implements==
【類的種類】:主要控制類(Control Class),service,dao

3.3 關(guān)聯(lián)(Association)
【關(guān)聯(lián)關(guān)系】:是一種擁有的關(guān)系,它使一個類知道另一個類的屬性和方法;如:老師與學(xué)生,丈夫與妻子關(guān)聯(lián)可以是雙向的,也可以是單向的。雙向的關(guān)聯(lián)可以有兩個箭頭或者沒有箭頭,單向的關(guān)聯(lián)有一個箭頭。
【代碼體現(xiàn)】:成員變量
【箭頭及指向】:帶普通箭頭的實心線,指向被擁有者
【類的種類】:主要是實體類(Entity Class),

上圖中,老師與學(xué)生是雙向關(guān)聯(lián),老師有多名學(xué)生,學(xué)生也可能有多名老師。但學(xué)生與某課程間的關(guān)系為單向關(guān)聯(lián),一名學(xué)生可能要上多門課程,課程是個抽象的東西他不擁有學(xué)生。
下圖為自身關(guān)聯(lián):

3.4 聚合(Aggregation)
【聚合關(guān)系】:是整體與部分的關(guān)系,且部分可以離開整體而單獨存在。如車和輪胎是整體和部分的關(guān)系,輪胎離開車仍然可以存在。
聚合關(guān)系是關(guān)聯(lián)關(guān)系的一種,是強的關(guān)聯(lián)關(guān)系;關(guān)聯(lián)和聚合在語法上無法區(qū)分,必須考察具體的邏輯關(guān)系。
【代碼體現(xiàn)】:成員變量
【箭頭及指向】:帶空心菱形的實心線,菱形指向整體
【類的種類】:主要是實體類(Entity Class)

3.5 組合(Composition)
【組合關(guān)系】:是整體與部分的關(guān)系,但部分不能離開整體而單獨存在。如公司和部門是整體和部分的關(guān)系,沒有公司就不存在部門。
組合關(guān)系是關(guān)聯(lián)關(guān)系的一種,是比聚合關(guān)系還要強的關(guān)系,它要求普通的聚合關(guān)系中代表整體的對象負(fù)責(zé)代表部分的對象的生命周期。
【代碼體現(xiàn)】:成員變量
【箭頭及指向】:帶實心菱形的實線,菱形指向整體

3.6 依賴(Dependency)
【依賴關(guān)系】:是一種使用的關(guān)系,即一個類的實現(xiàn)需要另一個類的協(xié)助,所以要盡量不使用雙向的互相依賴.
【代碼表現(xiàn)】:局部變量、方法的參數(shù)或者對靜態(tài)方法的調(diào)用,==@Autowired==
【箭頭及指向】:帶箭頭的虛線,指向被使用者

4、簡單的示例
4.1 實例分析1——登錄模塊
某基于C/S的即時聊天系統(tǒng)登錄模塊功能描述如下:
用戶通過登錄界面(LoginForm)輸入賬號和密碼,系統(tǒng)將輸入的賬號和密碼與存儲在數(shù)據(jù)庫(User)表中的用戶信息進行比較,驗證用戶輸入是否正確,如果輸入正確則進入主界面(MainForm),否則提示“輸入錯誤”。
根據(jù)以上描述繪制初始類圖。
參考解決方案:
參考類圖如下:

考慮到系統(tǒng)擴展性,在本實例中引入了抽象數(shù)據(jù)訪問接口IUserDAO,再將具體數(shù)據(jù)訪問對象注入到業(yè)務(wù)邏輯對象中,可通過配置文件(如XML文件)等方式來實現(xiàn),將具體的數(shù)據(jù)訪問類類名存儲在配置文件中,如果需要更換新的具體數(shù)據(jù)訪問對象,只需修改配置文件即可,原有程序代碼無須做任何修改。
類說明:

方法說明:

4.2 實例分析2——注冊模塊
某基于Java語言的C/S軟件需要提供注冊功能,該功能簡要描述如下:
用戶通過注冊界面(RegisterForm)輸入個人信息,用戶點擊“注冊”按鈕后將輸入的信息通過一個封裝用戶輸入數(shù)據(jù)的對象(UserDTO)傳遞給操作數(shù)據(jù)庫的數(shù)據(jù)訪問類,為了提高系統(tǒng)的擴展性,針對不同的數(shù)據(jù)庫可能需要提供不同的數(shù)據(jù)訪問類,因此提供了數(shù)據(jù)訪問類接口,如IUserDAO,每一個具體數(shù)據(jù)訪問類都是某一個數(shù)據(jù)訪問類接口的實現(xiàn)類,如OracleUserDAO就是一個專門用于訪問Oracle數(shù)據(jù)庫的數(shù)據(jù)訪問類。
根據(jù)以上描述繪制類圖。為了簡化類圖,個人信息僅包括賬號(userAccount)和密碼(userPassword),且界面類無需涉及界面細(xì)節(jié)元素。
參考解決方案:
在以上功能說明中,可以分析出該系統(tǒng)包括三個類和一個接口,這三個類分別是注冊界面類RegisterForm、用戶數(shù)據(jù)傳輸類UserDTO、oracle用戶數(shù)據(jù)訪問類OracleUserDAO,接口是抽象用戶數(shù)據(jù)訪問接口IUserDAO。它們之間的關(guān)系如下:
(1) 在RegisterForm中需要使用UserDTO類傳輸數(shù)據(jù)且需要使用數(shù)據(jù)訪問類來操作數(shù)據(jù)庫,因此RegisterForm與UserDTO和IUserDAO之間存在關(guān)聯(lián)關(guān)系,在RegisterForm中可以直接實例化UserDTO,因此它們之間可以使用組合關(guān)聯(lián)。
(2) 由于數(shù)據(jù)庫類型需要靈活更換,因此在RegisterForm中不能直接實例化IUserDAO的子類,可以針對接口IUserDAO編程,再通過注入的方式傳入一個IUserDAO接口的子類對象(在本書后續(xù)章節(jié)中將學(xué)習(xí)如何具體實現(xiàn)),因此RegisterForm和IUserDAO之間具有聚合關(guān)聯(lián)關(guān)系。
(3) OracleUserDAO是實現(xiàn)了IUserDAO接口的子類,因此它們之間具有類與接口的實現(xiàn)關(guān)系。
(4) 在聲明IUserDAO接口的增加用戶信息方法addUser()時,需要將在界面類中實例化的UserDTO對象作為參數(shù)傳遞進來,然后取出封裝在UserDTO對象中的數(shù)據(jù)插入數(shù)據(jù)庫,因此addUser()方法的函數(shù)原型可以定義為:public boolean addUser(UserDTO user),在IUserDAO的方法addUser()中將UserDTO類型的對象作為參數(shù),故IUserDAO與UserDTO存在依賴關(guān)系。
通過以上分析,該實例參考類圖如圖1所示:

注意:在繪制類圖或其他UML圖形時,可以通過注釋(Comment)來對圖中的符號或元素進行一些附加說明,如果需要詳細(xì)說明類圖中的某一方法的功能或者實現(xiàn)過程,可以使用如圖2所示表示方式:

4.3 實例分析3——售票機控制程序
某運輸公司決定為新的售票機開發(fā)車票銷售的控制軟件。圖I給出了售票機的面板示意圖以及相關(guān)的控制部件。

售票機相關(guān)部件的作用如下所述:
(1) 目的地鍵盤用來輸入行程目的地的代碼(例如,200表示總站)。
(2) 乘客可以通過車票鍵盤選擇車票種類(單程票、多次往返票和座席種類)。
(3) 繼續(xù)/取消鍵盤上的取消按鈕用于取消購票過程,繼續(xù)按鈕允許乘客連續(xù)購買多張票。
(4) 顯示屏顯示所有的系統(tǒng)輸出和用戶提示信息。
(5) 插卡口接受MCard(現(xiàn)金卡),硬幣口和紙幣槽接受現(xiàn)金。
(6) 打印機用于輸出車票。
(7) 所有部件均可實現(xiàn)自檢并恢復(fù)到初始狀態(tài)。
現(xiàn)采用面向?qū)ο蠓椒ㄩ_發(fā)該系統(tǒng),使用UML進行建模,繪制該系統(tǒng)的初始類圖。
參考解決方案:
參考類圖如下:

類說明:

方法說明:
