UML類圖(附IBM詳解索引及RSS訂閱)



閱讀提示:這是關於統一建模語言、即UML 裏採用的基本圖的文章。在這篇文章中,我將會討論結構圖,這是已經在 UML 2 中提出的一種新圖種類。由於本系列文章的目的是使人們瞭解記號元素及它們的含意,該文主要關注類圖。你很快就會知道這樣做的理由。隨後的文章將會覆蓋結構範疇中包含的其它圖。

這是關於統一建模語言、即UML 裏採用的基本圖的文章。在這篇文章中,我將會討論結構圖,這是已經在 UML 2 中提出的一種新圖種類。由於本系列文章的目的是使人們瞭解記號元素及它們的含意,該文主要關注類圖。你很快就會知道這樣做的理由。隨後的文章將會覆蓋結構範疇中包含的其它圖。

我也想提醒讀者,這一系列文章是關於 UML 記號元素的,所以這些文章並不意味着爲建模的最好方式提供指導方針,或是該如何決定哪些內容應該首先被建模。相反的,該文及本系列文章的目的主要是幫助大家對於記號元素 -- 語法和含義有一個基本的理解。藉由這些知識,你應該可以閱讀圖,並使用正確的記號元素創建你自己的圖。

這篇文章假定你對面向對象的設計已經有了基本的理解。你們當中如果有人需要一些面向對象概念的幫助,那麼可以訪問http://java.sun.com/docs/books/tutorial/java/concepts/,來獲得Sun公司關於面向對象編程的簡短指導。閱讀 “什麼是類?”和 什麼是繼承?” 章節,將提供給你足夠的理解,並對該文的閱讀會有所幫助。另外,David Taylor的書《 Object-Oriented Technologies: A Manager's Guide》提供了面向對象設計的優秀,高水平的說明,而無需對計算機編程有高深的理解。

UML 2 中的陰和陽

在 UML 2 中有二種基本的圖範疇:結構圖和行爲圖。每個 UML 圖都屬於這二個圖範疇。結構圖的目的是顯示建模系統的靜態結構。它們包括類,組件和(或)對象圖。另一方面,行爲圖顯示系統中的對象的動態行爲,包括如對象的方法,協作和活動之類的內容。行爲圖的實例是活動圖,用例圖和序列圖。

大體上的結構圖

如同我所說的,結構圖顯示建模系統的靜態結構。關注系統的元件,無需考慮時間。在系統內,靜態結構通過顯示類型和它們的實例進行傳播。除了顯示系統類型和它們的實例,結構圖至少也顯示了這些元素間的一些關係,可能的話,甚至也顯示它們的內部結構。

貫穿整個軟件生命週期,結構圖對於各種團隊成員都是有用的。一般而言,這些圖支持設計驗證,和個體與團隊間的設計交流。舉例來說,業務分析師可以使用類或對象圖,來爲當前的資產和資源建模,例如分類賬,產品或地理層次。架構師可以使用組件和部署圖,來測試/確認他們的設計是否充分。開發者可以使用類圖,來設計併爲系統的代碼(或即將成爲代碼的)類寫文檔。

特殊的類圖

UML 2 把結構圖看成一個分類;這裏並不存在稱爲“結構圖”的圖。然而,類圖提供結構圖類型的一個主要實例,併爲我們提供一組記號元素的初始集,供所有其它結構圖使用。由於類圖是如此基本,本文的剩餘部分將會把重點集中在類圖記號集。在本文的結尾,你將對於如何畫UML 2類圖有所瞭解,而且對於理解在後面文章中將涉及的其他結構圖有一個穩固的基礎。

基礎

如先前所提到的,類圖的目的是顯示建模系統的類型。在大多數的 UML 模型中這些類型包括:

  • 接口
  • 數據類型
  • 組件

UML 爲這些類型起了一個特別的名字:“分類器”。通常地,你可以把分類器當做類,但在技術上,分類器是更爲普遍的術語,它還是引用上面的其它三種類型爲好。

類名

類的 UML 表示是一個長方形,垂直地分爲三個區,如圖 1 所示。頂部區域顯示類的名字。中間的區域列出類的屬性。底部的區域列出類的操作。當在一個類圖上畫一個類元素時,你必須要有頂端的區域,下面的二個區域是可選擇的(當圖描述僅僅用於顯示分類器間關係的高層細節時,下面的兩個區域是不必要的)。圖 1 顯示一個航線班機如何作爲 UML 類建模。正如我們所能見到的,名字是 Flight,我們可以在中間區域看到Flight類的3個屬性:flightNumber,departureTime 和 flightDuration。在底部區域中我們可以看到Flight類有兩個操作:delayFlight 和 getArrivalTime。



圖 1: Flight類的類圖

類屬性列表

類的屬性節(中部區域)在分隔線上列出每一個類的屬性。屬性節是可選擇的,要是一用它,就包含類的列表顯示的每個屬性。該線用如下格式:

name : attribute type
flightNumber : Integer

繼續我們的Flight類的例子,我們可以使用屬性類型信息來描述類的屬性,如表 1 所示。

表 1:具有關聯類型的Flight類的屬性名字

屬性名稱 屬性類型
flightNumber Integer
departureTime Date
flightDuration Minutes

在業務類圖中,屬性類型通常與單位相符,這對於圖的可能讀者是有意義的(例如,分鐘,美元,等等)。然而,用於生成代碼的類圖,要求類的屬性類型必須限制在由程序語言提供的類型之中,或包含於在系統中實現的、模型的類型之中。

在類圖上顯示具有默認值的特定屬性,有時是有用的(例如,在銀行賬戶應用程序中,一個新的銀行賬戶會以零爲初始值)。UML 規範允許在屬性列表節中,通過使用如下的記號作爲默認值的標識:

name : attribute type = default value

舉例來說:

balance : Dollars = 0

顯示屬性默認值是可選擇的;圖 2 顯示一個銀行賬戶類具有一個名爲 balance的類型,它的默認值爲0。

 圖 2:顯示默認爲0美元的balance屬性值的銀行賬戶類圖。

類操作列表

 

類操作記錄在類圖長方形的第三個(最低的)區域中,它也是可選擇的。和屬性一樣,類的操作以列表格式顯示,每個操作在它自己線上。操作使用下列記號表現:

name(parameter list) : type of value returned

下面的表 2 中Flight類操作的映射。

表 2:從圖 2 映射的Flight類的操作

操作名稱 返回參數 值類型
delayFlight
Name Type
numberOfMinutes Minutes
N/A
getArrivalTime N/A Date

圖3顯示,delayFlight 操作有一個Minutes類型的輸入參數 -- numberOfMinutes。然而,delayFlight 操作沒有返回值。1 當一個操作有參數時,參數被放在操作的括號內;每個參數都使用這樣的格式:“參數名:參數類型”。



圖 3:Flight類操作參數,包括可選擇的“in”標識。

當文檔化操作參數時,你可能使用一個可選擇的指示器,以顯示參數到操作的輸入參數、或輸出參數。這個可選擇的指示器以“in”或“out”出現,如圖3中的操作區域所示。一般來說,除非將使用一種早期的程序編程語言,如Fortran ,這些指示器可能會有所幫助,否則它們是不必要的。然而,在 C++和Java中,所有的參數是“in”參數,而且按照UML規範,既然“in”是參數的默認類型,大多數人將會遺漏輸入/輸出指示器。

繼承

在面向對象的設計中一個非常重要的概念,繼承,指的是一個類(子類)繼承另外的一個類(超類)的同一功能,並增加它自己的新功能(一個非技術性的比喻,想象我繼承了我母親的一般的音樂能力,但是在我的家裏,我是唯一一個玩電吉他的人)的能力。爲了在一個類圖上建模繼承,從子類(要繼承行爲的類)拉出一條閉合的,單鍵頭(或三角形)的實線指向超類。考慮銀行賬戶的類型:圖 4 顯示 CheckingAccount 和 SavingsAccount 類如何從 BankAccount 類繼承而來。



圖 4: 繼承通過指向超類的一條閉合的,單箭頭的實線表示。

在圖 4 中,繼承關係由每個超類的單獨的線畫出,這是在IBM Rational Rose和IBM Rational XDE中使用的方法。然而,有一種稱爲 樹標記的備選方法可以畫出繼承關係。當存在兩個或更多子類時,如圖 4 中所示,除了繼承線象樹枝一樣混在一起外,你可以使用樹形記號。圖 5 是重繪的與圖 4 一樣的繼承,但是這次使用了樹形記號。



圖 5: 一個使用樹形記號的繼承實例

抽象類及操作

細心的讀者會注意到,在圖 4 和 圖5 中的圖中,類名BankAccount和withdrawal操作使用斜體。這表示,BankAccount 類是一個抽象類,而withdrawal方法是抽象的操作。換句話說,BankAccount 類使用withdrawal規定抽象操作,並且CheckingAccount 和 SavingsAccount 兩個子類都分別地執行它們各自版本的操作。

然而,超類(父類)不一定要是抽象類。標準類作爲超類是正常的。

類操作列表

 

類操作記錄在類圖長方形的第三個(最低的)區域中,它也是可選擇的。和屬性一樣,類的操作以列表格式顯示,每個操作在它自己線上。操作使用下列記號表現:

name(parameter list) : type of value returned

下面的表 2 中Flight類操作的映射。

表 2:從圖 2 映射的Flight類的操作

操作名稱 返回參數 值類型
delayFlight
Name Type
numberOfMinutes Minutes
N/A
getArrivalTime N/A Date

圖3顯示,delayFlight 操作有一個Minutes類型的輸入參數 -- numberOfMinutes。然而,delayFlight 操作沒有返回值。1 當一個操作有參數時,參數被放在操作的括號內;每個參數都使用這樣的格式:“參數名:參數類型”。



圖 3:Flight類操作參數,包括可選擇的“in”標識。

當文檔化操作參數時,你可能使用一個可選擇的指示器,以顯示參數到操作的輸入參數、或輸出參數。這個可選擇的指示器以“in”或“out”出現,如圖3中的操作區域所示。一般來說,除非將使用一種早期的程序編程語言,如Fortran ,這些指示器可能會有所幫助,否則它們是不必要的。然而,在 C++和Java中,所有的參數是“in”參數,而且按照UML規範,既然“in”是參數的默認類型,大多數人將會遺漏輸入/輸出指示器。

繼承

在面向對象的設計中一個非常重要的概念,繼承,指的是一個類(子類)繼承另外的一個類(超類)的同一功能,並增加它自己的新功能(一個非技術性的比喻,想象我繼承了我母親的一般的音樂能力,但是在我的家裏,我是唯一一個玩電吉他的人)的能力。爲了在一個類圖上建模繼承,從子類(要繼承行爲的類)拉出一條閉合的,單鍵頭(或三角形)的實線指向超類。考慮銀行賬戶的類型:圖 4 顯示 CheckingAccount 和 SavingsAccount 類如何從 BankAccount 類繼承而來。



圖 4: 繼承通過指向超類的一條閉合的,單箭頭的實線表示。

在圖 4 中,繼承關係由每個超類的單獨的線畫出,這是在IBM Rational Rose和IBM Rational XDE中使用的方法。然而,有一種稱爲 樹標記的備選方法可以畫出繼承關係。當存在兩個或更多子類時,如圖 4 中所示,除了繼承線象樹枝一樣混在一起外,你可以使用樹形記號。圖 5 是重繪的與圖 4 一樣的繼承,但是這次使用了樹形記號。



圖 5: 一個使用樹形記號的繼承實例

抽象類及操作

細心的讀者會注意到,在圖 4 和 圖5 中的圖中,類名BankAccount和withdrawal操作使用斜體。這表示,BankAccount 類是一個抽象類,而withdrawal方法是抽象的操作。換句話說,BankAccount 類使用withdrawal規定抽象操作,並且CheckingAccount 和 SavingsAccount 兩個子類都分別地執行它們各自版本的操作。

然而,超類(父類)不一定要是抽象類。標準類作爲超類是正常的。

類操作列表

 

類操作記錄在類圖長方形的第三個(最低的)區域中,它也是可選擇的。和屬性一樣,類的操作以列表格式顯示,每個操作在它自己線上。操作使用下列記號表現:

name(parameter list) : type of value returned

下面的表 2 中Flight類操作的映射。

表 2:從圖 2 映射的Flight類的操作

操作名稱 返回參數 值類型
delayFlight
Name Type
numberOfMinutes Minutes
N/A
getArrivalTime N/A Date

圖3顯示,delayFlight 操作有一個Minutes類型的輸入參數 -- numberOfMinutes。然而,delayFlight 操作沒有返回值。1 當一個操作有參數時,參數被放在操作的括號內;每個參數都使用這樣的格式:“參數名:參數類型”。



圖 3:Flight類操作參數,包括可選擇的“in”標識。

當文檔化操作參數時,你可能使用一個可選擇的指示器,以顯示參數到操作的輸入參數、或輸出參數。這個可選擇的指示器以“in”或“out”出現,如圖3中的操作區域所示。一般來說,除非將使用一種早期的程序編程語言,如Fortran ,這些指示器可能會有所幫助,否則它們是不必要的。然而,在 C++和Java中,所有的參數是“in”參數,而且按照UML規範,既然“in”是參數的默認類型,大多數人將會遺漏輸入/輸出指示器。

繼承

在面向對象的設計中一個非常重要的概念,繼承,指的是一個類(子類)繼承另外的一個類(超類)的同一功能,並增加它自己的新功能(一個非技術性的比喻,想象我繼承了我母親的一般的音樂能力,但是在我的家裏,我是唯一一個玩電吉他的人)的能力。爲了在一個類圖上建模繼承,從子類(要繼承行爲的類)拉出一條閉合的,單鍵頭(或三角形)的實線指向超類。考慮銀行賬戶的類型:圖 4 顯示 CheckingAccount 和 SavingsAccount 類如何從 BankAccount 類繼承而來。



圖 4: 繼承通過指向超類的一條閉合的,單箭頭的實線表示。

在圖 4 中,繼承關係由每個超類的單獨的線畫出,這是在IBM Rational Rose和IBM Rational XDE中使用的方法。然而,有一種稱爲 樹標記的備選方法可以畫出繼承關係。當存在兩個或更多子類時,如圖 4 中所示,除了繼承線象樹枝一樣混在一起外,你可以使用樹形記號。圖 5 是重繪的與圖 4 一樣的繼承,但是這次使用了樹形記號。



圖 5: 一個使用樹形記號的繼承實例

抽象類及操作

細心的讀者會注意到,在圖 4 和 圖5 中的圖中,類名BankAccount和withdrawal操作使用斜體。這表示,BankAccount 類是一個抽象類,而withdrawal方法是抽象的操作。換句話說,BankAccount 類使用withdrawal規定抽象操作,並且CheckingAccount 和 SavingsAccount 兩個子類都分別地執行它們各自版本的操作。

然而,超類(父類)不一定要是抽象類。標準類作爲超類是正常的。

可見性

在面向對象的設計中,存在屬性及操作可見性的記號。UML識別四種類型的可見性:public,protected,private及package。

 

UML規範並不要求屬性及操作可見性必須顯示在類圖上,但是它要求爲每個屬性及操作定義可見性。爲了在類圖上的顯示可見性,放置可見性標誌於屬性或操作的名字之前。雖然UML指定四種可見性類型,但是實際的編程語言可能增加額外的可見性,或不支持%20UML%20定義的可見性。表4顯示了UML支持的可見性類型的不同標誌。

表4:UML支持的可見性類型的標誌

標誌 可見性類型
+ Public
# Protected
- Private
~ Package

現在,讓我們看一個類,以說明屬性及操作的可見性類型。在圖 15 中,所有的屬性及操作都是public,除了 updateBalance 操作。updateBalance 操作是protected。



圖 15:一個 BankAccount 類說明它的屬性及操作的可見性

UML 2 補充

既然我們已經覆蓋了基礎和高級主題,我們將覆蓋一些由UML 1. x增加的類圖的新記號。

實例

當一個系統結構建模時,顯示例子類實例有時候是有用的。爲了這種結構建模,UML 2 提供 實例規範 元素,它顯示在系統中使用例子(或現實)實例的值得注意的信息。

實例的記號和類一樣,但是取代頂端區域中僅有的類名,它的名字是經過拼接的:

Instance Name : Class Name

舉例來說:

Donald : Person

因爲顯示實例的目的是顯示值得注意的或相關的信息,沒必要在你的模型中包含整個實體屬性及操作。相反地,僅僅顯示感興趣的屬性及其值是完全恰當的。如圖16所描述。



圖 16:Plane類的一個實例例子(只顯示感興趣的屬性值)

然而,僅僅表現一些實例而沒有它們的關係不太實用;因此,UML 2 也允許在實體層的關係/關聯建模。繪製關聯與一般的類關係的規則一樣,除了在建模關聯時有一個附加的要求。附加的限制是,關聯關係必須與類圖的關係相一致,而且關聯的角色名字也必須與類圖相一致。它的一個例子顯示於圖 17 中。在這個例子中,實例是圖 6 中類圖的例子實例。



圖 17:圖 6 中用實例代替類的例子

圖 17 有Flight類的二個實例,因爲類圖指出了在Plane類和Flight類之間的關係是 0或多。因此,我們的例子給出了兩個與NX0337 Plane實例相關的Flight實例。

角色

建模類的實例有時比期望的更爲詳細。有時,你可能僅僅想要在一個較多的一般層次做類關係的模型。在這種情況下,你應該使用 角色 記號。角色記號類似於實例記號。爲了建立類的角色模型,你畫一個方格,並在內部放置類的角色名及類名,作爲實體記號,但是在這情況你不能加下劃線。圖 18 顯示一個由圖 14 中圖描述的僱員類扮演的角色實例。在圖 18 中,我們可以認爲,即使僱員類與它本身相關,關係確實是關於僱員之間扮演經理及團隊成員的角色。



圖 18:一個類圖顯示圖14中扮演不同角色的類

注意,你不能在純粹類圖中做類角色的建模,即使圖 18顯示你可以這麼做。爲了使用角色記號,你將會需要使用下面討論的內部結構記號。

內部的結構

UML 2 結構圖的更有用的功能之一是新的內部結構記號。它允許你顯示一個類或另外的一個分類器如何在內部構成。這在 UML 1. x 中是不可能的,因爲記號限制你只能顯示一個類所擁有的聚合關係。現在,在 UML 2 中,內部的結構記號讓你更清楚地顯示類的各個部分如何保持關係。

讓我們看一個實例。在圖 18 中我們有一個類圖以表現一個Plane類如何由四個引擎和兩個控制軟件對象組成。從這個圖中省略的東西是顯示關於飛機部件如何被裝配的一些信息。從圖 18 的圖,你無法說明,是每個控制軟件對象控制兩個引擎,還是一個控制軟件對象控制三個引擎,而另一個控制一個引擎。



圖 19: 只顯示對象之間關係的類圖

繪製類的內在結構將會改善這種狀態。開始時,你通過用二個區域畫一個方格。最頂端的區域包含類名字,而較低的區域包含類的內部結構,顯示在它們父類中承擔不同角色的部分類,角色中的每個部分類也關係到其它類。圖 19 顯示了Plane類的內部結構;注意內部結構如何澄清混亂性。



圖 20:Plane類的內部結構例子。

在圖 20 中Plane有兩個 ControlSoftware 對象,而且每個控制二個引擎。在圖左邊上的 ControlSoftware(control1)控制引擎 1 和 2 。在圖右邊的 ControlSoftware(control2)控制引擎 3 和 4 。

結論

至少存在兩個瞭解類圖的重要理由。第一個是它顯示系統分類器的靜態結構;第二個理由是圖爲UML描述的其他結構圖提供了基本記號。開發者將會認爲類圖是爲他們特別建立的;但是其他的團隊成員將發現它們也是有用的。業務分析師可以用類圖,爲系統的業務遠景建模。正如我們將會在本系列關於 UML 基礎的文章中見到的,其他的圖 -- 包括活動圖,序列圖和狀態圖——參考類圖中的類建模和文檔化。

關於“UML 基礎”的本系列的後面的元件圖。

腳註

1 delayFlight沒有返回值,因爲我作出了設計決定,不要返回值。有一點可以爭論的是,延遲操作應該返回新的到達時間,而且,如果是這種情形,操作屬性將顯示爲delayFlight(numberOfMinutes : Minutes) : Date。

2可能看起來很奇怪, BankAccount 類不知道 OverdrawnAccountsReport 類。這個建模使報表類可以知道它們報告的業務類,但是業務類不知道它們正在被報告。這解開兩個對象的耦合,並因此使系統變得更能適應變化。

3 軟件包對於組織你的模型類是龐大的,但是記住重要的一點是,你的類圖應該是關於建模系統的容易交流的信息。在你的軟件包有許多類的情況下,最好使用多個主題類圖,而不是僅僅產生一個大的類圖。

4 要理解重要一點,當我說“所有的那些成員”時,我僅僅意味着在當前圖中的類將顯示出來。顯示一個有內容的軟件包的圖,不需要顯示它的所有內容。它可以依照一些準則,顯示包含元素的子集,這個準則就是並非所有的軟件包分類器都是必需的。

5 當畫一個類圖時,在 UML 規範中,全部要做的只是把類放入長方形的頂部區域,而你同理處理接口;然而,UML 規範認爲,在這個區域放置“class”文本是可選的,如果類沒有顯示,那麼它應該被假設。

參考資料 您可以參閱本文在 developerWorks 全球站點上的 英文原文

推薦:UML序列圖詳解 (責任編輯:銘銘)

發佈了31 篇原創文章 · 獲贊 16 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章