UML類圖關係大全

轉自:http://www.360doc.com/content/10/0305/10/899290_17628362.shtml

1、關聯

雙向關聯:
C1-C2:指雙方都知道對方的存在,都可以調用對方的公共屬性和方法。

在 GOF的設計模式書上是這樣描述的:雖然在分析階段這種關係是適用的,但我們覺得它對於描述設計模式內的類關係來說顯得太抽象了,因爲在設計階段關聯關係必須被映射爲對象引用或指針。對象引用本身就是有向的,更適合表達我們所討論的那種關係。所以這種關係在設計的時候比較少用到,關聯一般都是有向的。

使用ROSE 生成的代碼是這樣的:

 class C1 
{
 public:
     C2* theC2;

 };

 class C2 
 {
 public:
     C1* theC1;

 };

雙向關聯在代碼的表現爲雙方都擁有對方的一個指針,當然也可以是引用或者是值。





單向關聯:
C3->C4:表示相識關係,指C3知道C4,C3可以調用C4的公共屬性和方法。沒有生命期的依賴。一般是表示爲一種引用。

生成代碼如下:

 class C3 
{
 public:
     C4* theC4;

 };

 class C4 
{

 };

單向關聯的代碼就表現爲C3有C4的指針,而C4對C3一無所知。



自身關聯(反身關聯):
自己引用自己,帶着一個自己的引用。

代碼如下:

 class C14 
{
 public:
     C14* theC14;

 };

就是在自己的內部有着一個自身的引用。

2、聚合/組合

當類之間有整體-部分關係的時候,我們就可以使用組合或者聚合。



聚合:表示C9聚合C10,但是C10可以離開C9而獨立存在(獨立存在的意思是在某個應用的問題域中這個類的存在有意義。這句話怎麼解,請看下面組合裏的解釋)。

代碼如下:

 class C9 
{
 public:
     C10 theC10;

 };

 class C10 
{

 };
 




組合(也有人稱爲包容):一般是實心菱形加實線箭頭表示,如上圖所示,表示的是C8被C7包容,而且C8不能離開C7而獨立存在。但這是視問題域而定的,例如在關心汽車的領域裏,輪胎是一定要組合在汽車類中的,因爲它離開了汽車就沒有意義了。但是在賣輪胎的店鋪業務裏,就算輪胎離開了汽車,它也是有意義的,這就可以用聚合了。在《敏捷開發》中還說到,A組合B,則A需要知道B的生存週期,即可能A負責生成或者釋放B,或者A通過某種途徑知道B的生成和釋放。

他們的代碼如下:

 class C7 
{
 public:
     C8 theC8;

 };

 class C8 
{
 };

可以看到,代碼和聚合是一樣的。具體如何區別,可能就只能用語義來區分了。

3、依賴



依賴:
指C5可能要用到C6的一些方法,也可以這樣說,要完成C5裏的所有功能,一定要有C6的方法協助才行。C5依賴於C6的定義,一般是在C5類的頭文件中包含了C6的頭文件。ROSE對依賴關係不產生屬性。

注意,要避免雙向依賴。一般來說,不應該存在雙向依賴。

ROSE生成的代碼如下:

 // C5.h
 #include "C6.h"

 class C5 
{

 };

 // C6.h
 #include "C5.h"

 class C6
 {

 };

雖然ROSE不生成屬性,但在形式上一般是A中的某個方法把B的對象作爲參數使用(假設A依賴於B)。如下:

 #include "B.h"
 class A
 {
           void Func(B &b);
 }

那依賴和聚合/組合、關聯等有什麼不同呢?

關聯是類之間的一種關係,例如老師教學生,老公和老婆,水壺裝水等就是一種關係。這種關係是非常明顯的,在問題領域中通過分析直接就能得出。

依賴是一種弱關聯,只要一個類用到另一個類,但是和另一個類的關係不是太明顯的時候(可以說是“uses”了那個類),就可以把這種關係看成是依賴,依賴也可說是一種偶然的關係,而不是必然的關係,就是“我在某個方法中偶然用到了它,但在現實中我和它並沒多大關係”。例如我和錘子,我和錘子本來是沒關係的,但在有一次要釘釘子的時候,我用到了它,這就是一種依賴,依賴錘子完成釘釘子這件事情。

組合是一種整體-部分的關係,在問題域中這種關係很明顯,直接分析就可以得出的。例如輪胎是車的一部分,樹葉是樹的一部分,手腳是身體的一部分這種的關係,非常明顯的整體-部分關係。

上述的幾種關係(關聯、聚合/組合、依賴)在代碼中可能以指針、引用、值等的方式在另一個類中出現,不拘於形式,但在邏輯上他們就有以上的區別。

這裏還要說明一下,所謂的這些關係只是在某個問題域纔有效,離開了這個問題域,可能這些關係就不成立了,例如可能在某個問題域中,我是一個木匠,需要拿着錘子去幹活,可能整個問題的描述就是我拿着錘子怎麼釘桌子,釘椅子,釘櫃子;既然整個問題就是描述這個,我和錘子就不僅是偶然的依賴關係了,我和錘子的關係變得非常的緊密,可能就上升爲組合關係(讓我突然想起武俠小說的劍不離身,劍亡人亡...)。這個例子可能有點荒謬,但也是爲了說明一個道理,就是關係和類一樣,它們都是在一個問題領域中才成立的,離開了這個問題域,他們可能就不復存在了。


4、泛化(繼承)



泛化關係:如果兩個類存在泛化的關係時就使用,例如父和子,動物和老虎,植物和花等。
ROSE生成的代碼很簡單,如下:

 #include "C11.h"

 class C12 : public C11
 {
 };


5、這裏順便提一下模板



上面的圖對應的代碼如下:

 template<int>
 class C13 
{
 };

這裏再說一下重複度,其實看完了上面的描述之後,我們應該清楚了各個關係間的關係以及具體對應到代碼是怎麼樣的,所謂的重複度,也只不過是上面的擴展,例如A和B有着“1對多”的重複度,那在A中就有一個列表,保存着B對象的N個引用,就是這樣而已。

好了,到這裏,已經把上面的類圖關係說完了,希望你能有所收穫了,我也費了不少工夫啊(畫圖、生成代碼、截圖、寫到BLOG上,唉,一頭大汗)。不過如果能讓你徹底理解UML類圖的這些關係,也值得了。:)


+++++++++++++++++++++++++++++++++++++++++++++++++++++

在UML建模中,對類圖上出現元素的理解是至關重要的。開發者必須理解如何將類圖上出現的元素轉換到Java中。以java爲代表結合網上的一些實例,下面是個人一些基本收集與總結:
基本元素符號:
1. 類(Classes)
類包含3個組成部分。第一個是Java中定義的類名。第二個是屬性(attributes)。第三個是該類提供的方法。
屬性和操作之前可附加一個可見性修飾符。加號(+)表示具有公共可見性。減號(-)表示私有可見性。#號表示受保護的可見性。省略這些修飾符表示具有package(包)級別的可見性。如果屬性或操作具有下劃線,表明它是靜態的。在操作中,可同時列出它接受的參數,以及返回類型,如下圖所示:

  2. 包(Package)
包是一種常規用途的組合機制。UML中的一個包直接對應於Java中的一個包。在Java 中,一個包可能含有其他包、類或者同時含有這兩者。進行建模時,你通常擁有邏輯性的包,它主要用於對你的模型進行組織。你還會擁有物理性的包,它直接轉換成系統中的Java包。每個包的名稱對這個包進行了惟一性的標識。

  3. 接口(Interface)
接口是一系列操作的集合,它指定了一個類所提供的服務。它直接對應於Java中的一個接口類型。接口既可用下面的那個圖標來表示(上面一個圓圈符號,圓圈符號下面是接口名,中間是直線,直線下面是方法名),也可由附加了<<interface>>的一個標準類來表示。通常,根據接口在類圖上的樣子,就能知道與其他類的關係。

關 系:
1. 依賴(Dependency)
實體之間一個“使用”關係暗示一個實體的規範發生變化後,可能影響依賴於它的其他實例。更具體地說,它可轉換爲對不在實例作用域內的一個類或對象的任何類型的引用。其中包括一個局部變量,對通過方法調用而獲得的一個對象的引用(如下例所示),或者對一個類的靜態方法的引用(同時不存在那個類的一個實例)。也可利用“依賴”來表示包和包之間的關係。由於包中含有類,所以你可根據那些包中的各個類之間的關係,表示出包和包的關係。

  2. 關聯(Association)
實體之間的一個結構化關係表明對象是相互連接的。箭頭是可選的,它用於指定導航能力。如果沒有箭頭,暗示是一種雙向的導航能力。在Java中,關聯轉換爲一個實例作用域的變量,就像圖E的“Java”區域所展示的代碼那樣。可爲一個關聯附加其他修飾符。多重性(Multiplicity)修飾符暗示着實例之間的關係。在示範代碼中,Employee可以有0個或更多的TimeCard對象。但是,每個TimeCard只從屬於單獨一個Employee。

3. 聚合(Aggregation)
聚合是關聯的一種形式,代表兩個類之間的整體/局部關係。聚合暗示着整體在概念上處於比局部更高的一個級別,而關聯暗示兩個類在概念上位於相同的級別。聚合也轉換成Java中的一個實例作用域變量。
關聯和聚合的區別純粹是概念上的,而且嚴格反映在語義上。聚合還暗示着實例圖中不存在迴路。換言之,只能是一種單向關係。

  4. 合成(Composition)
合成是聚合的一種特殊形式,暗示“局部”在“整體”內部的生存期職責。合成也是非共享的。所以,雖然局部不一定要隨整體的銷燬而被銷燬,但整體要麼負責保持局部的存活狀態,要麼負責將其銷燬。
局部不可與其他整體共享。但是,整體可將所有權轉交給另一個對象,後者隨即將承擔生存期職責。Employee和TimeCard的關係或許更適合表示成“合成”,而不是表示成“關聯”。

  5. 泛化(Generalization)
泛化表示一個更泛化的元素和一個更具體的元素之間的關係。泛化是用於對繼承進行建模的UML元素。在Java中,用extends關鍵字來直接表示這種關係。

  6. 實現(Realization)
實例關係指定兩個實體之間的一個合同。換言之,一個實體定義一個合同,而另一個實體保證履行該合同。對Java應用程序進行建模時,實現關係可直接用implements關鍵字來表示。

像聚合還分爲:非共享聚合、共享聚合、複合聚合等。以及其它內容,下次再補充。





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 兩個子類都分別地執行它們各自版本的操作。

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

關聯
當你係統建模時,特定的對象間將會彼此關聯,而且這些關聯本身需要被清晰地建模。有五種關聯。在這一部分中,我將會討論它們中的兩個 -- 雙向的關聯和單向的關聯,而且我將會在Beyond the basics部分討論剩下的三種關聯類型。請注意,關於何時該使用每種類型關聯的詳細討論,不屬於本文的範圍。相反的,我將會把重點集中在每種關聯的用途,並說明如何在類圖上畫出關聯。

雙向(標準)的關聯
關聯是兩個類間的聯接。關聯總是被假定是雙向的;這意味着,兩個類彼此知道它們間的聯繫,除非你限定一些其它類型的關聯。回顧一下Flight 的例子,圖 6 顯示了在Flight類和Plane類之間的一個標準類型的關聯。


圖 6:在一個Flight類和Plane類之間的雙向關聯的實例

一個雙向關聯用兩個類間的實線表示。在線的任一端,你放置一個角色名和多重值。圖 6 顯示Flight與一個特定的Plane相關聯,而且Flight類知道這個關聯。因爲角色名以Plane類表示,所以Plane承擔關聯中的 “assignedPlane”角色。緊接於Plane類後面的多重值描述0...1表示,當一個Flight實體存在時,可以有一個或沒有Plane與之關聯(也就是,Plane可能還沒有被分配)。圖 6 也顯示Plane知道它與Flight類的關聯。在這個關聯中,Flight承擔“assignedFlights”角色;圖 6 的圖告訴我們,Plane實體可以不與flight關聯(例如,它是一架全新的飛機)或與沒有上限的flight(例如,一架已經服役5年的飛機)關聯。

由於對那些在關聯尾部可能出現的多重值描述感到疑惑,下面的表3列出了一些多重值及它們含義的例子。

表 3: 多重值和它們的表示

可能的多重值描述
表示 含義
0..1 0個或1個
1 只能1個
0..* 0個或多個
* 0個或多個
1..* 1個或我個
3 只能3個
0..5 0到5個
5..15 5到15個

單向關聯

在一個單向關聯中,兩個類是相關的,但是隻有一個類知道這種聯繫的存在。圖 7 顯示單向關聯的透支財務報告的一個實例。


圖 7: 單向關聯一個實例:OverdrawnAccountsReport 類 BankAccount 類,而 BankAccount 類則對關聯一無所知。

一個單向的關聯,表示爲一條帶有指向已知類的開放箭頭(不關閉的箭頭或三角形,用於標誌繼承)的實線。如同標準關聯,單向關聯包括一個角色名和一個多重值描述,但是與標準的雙向關聯不同的時,單向關聯只包含已知類的角色名和多重值描述。在圖 7 中的例子中,OverdrawnAccountsReport 知道 BankAccount 類,而且知道 BankAccount 類扮演“overdrawnAccounts”的角色。然而,和標準關聯不同,BankAccount 類並不知道它與 OverdrawnAccountsReport 相關聯。2

軟件包
不可避免,如果你正在爲一個大的系統或大的業務領域建模,在你的模型中將會有許多不同的分類器。管理所有的類將是一件令人生畏的任務;所以,UML 提供一個稱爲軟件包的組織元素。軟件包使建模者能夠組織模型分類器到名字空間中,這有些象文件系統中的文件夾。把一個系統分爲多個軟件包使系統變成容易理解,尤其是在每個軟件包都表現系統的一個特定部分時。3

在圖中存在兩種方法表示軟件包。並沒有規則要求使用哪種標記,除了用你個人的判斷:哪種更便於閱讀你畫的類圖。兩種方法都是由一個較小的長方形(用於定位)嵌套在一個大的長方形中開始的,如圖 8 所示。但是建模者必須決定包的成員如何表示,如下:

  • 如果建模者決定在大長方形中顯示軟件包的成員,則所有的那些成員4 需要被放置在長方形裏面。另外,所有軟件包的名字需要放在軟件包的較小長方形之內(如圖 8 的顯示)。
  • 如果建模者決定在大的長方形之外顯示軟件包成員,則所有將會在圖上顯示的成員都需要被置於長方形之外。爲了顯示屬於軟件包的分類器屬於,從每個分類器畫一條線到裏面有加號的圓周,這些圓周粘附在軟件包之上(圖9)。


圖 8:在軟件包的長方形內顯示軟件包成員的軟件包元素例子


圖 9:一個通過連接線表現軟件包成員的軟件包例子

瞭解基礎重要性

在 UML 2 中,瞭解類圖的基礎更爲重要。這是因爲類圖爲所有的其他結構圖提供基本的構建塊。如組件或對象圖(僅僅是舉了些例子)。

超過基礎
到此爲止,我已經介紹了類圖的基礎,但是請繼續往下讀!在下面的部分中,我將會引導你到你會使用的類圖的更重要的方面。這些包括UML 2 規範中的接口,其它的三種關聯類型,可見性和其他補充。

接口
在本文的前面,我建議你以類來考慮分類器。事實上,分類器是一個更爲一般的概念,它包括數據類型和接口。

關於何時、以及如何高效地在系統結構圖中使用數據類型和接口的完整討論,不在本文的討論範圍之內。既然這樣,我爲什麼要在這裏提及數據類型和接口呢?你可能想在結構圖上模仿這些分類器類型,在這個時候,使用正確的記號來表示,或者至少知道這些分類器類型是重要的。不正確地繪製這些分類器,很有可能將使你的結構圖讀者感到混亂,以後的系統將不能適應需求。

一個類和一個接口不同:一個類可以有它形態的真實實例,然而一個接口必須至少有一個類來實現它。在 UML 2 中,一個接口被認爲是類建模元素的特殊化。因此,接口就象類那樣繪製,但是長方形的頂部區域也有文本“interface”,如圖 10 所示5


圖 10:Professor類和Student類實現Person接口的類圖實例

在圖 10 中顯示的圖中,Professor和Student類都實現了Person的接口,但並不從它繼承。我們知道這一點是由於下面兩個原因:1) Person對象作爲接口被定義 -- 它在對象的名字區域中有“interface”文本,而且我們看到由於Professor和Student對象根據畫類對象的規則(在它們的名字區域中沒有額外的分類器文本)標示,所以它們是 類對象。 2) 我們知道繼承在這裏沒有被顯示,因爲與帶箭頭的線是點線而不是實線。如圖 10 所示,一條帶有閉合的單向箭頭的點 線意味着實現(或實施);正如我們在圖 4 中所見到的,一條帶有閉合單向箭頭的實線表示繼承。

更多的關聯
在上面,我討論了雙向關聯和單向關聯。現在,我將會介紹剩下的三種類型的關聯。

關聯類
在關聯建模中,存在一些情況下,你需要包括其它類,因爲它包含了關於關聯的有價值的信息。對於這種情況,你會使用 關聯類 來綁定你的基本關聯。關聯類和一般類一樣表示。不同的是,主類和關聯類之間用一條相交的點線連接。圖 11 顯示一個航空工業實例的關聯類。


圖 11:增加關聯類 MileageCredit

在圖 11 中顯示的類圖中,在Flight類和 FrequentFlyer 類之間的關聯,產生了稱爲 MileageCredit的關聯類。這意味當Flight類的一個實例關聯到 FrequentFlyer 類的一個實例時,將會產生 MileageCredit 類的一個實例。

聚合
聚合是一種特別類型的關聯,用於描述“總體到局部”的關係。在基本的聚合關係中, 部分類 的生命週期獨立於 整體類 的生命週期。

舉例來說,我們可以想象,車 是一個整體實體,而 車輪輪胎是整輛車的一部分。輪胎可以在安置到車時的前幾個星期被製造,並放置於倉庫中。在這個實例中,Wheel類實例清楚地獨立地Car類實例而存在。然而,有些情況下, 部分 類的生命週期並 不 獨立於 整體 類的生命週期 -- 這稱爲合成聚合。舉例來說,考慮公司與部門的關係。 公司和部門都建模成類,在公司存在之前,部門不能存在。這裏Department類的實例依賴於Company類的實例而存在。

讓我們更進一步探討基本聚合和組合聚合。

基本聚合
有聚合關係的關聯指出,某個類是另外某個類的一部分。在一個聚合關係中,子類實例可以比父類存在更長的時間。爲了表現一個聚合關係,你畫一條從父類到部分類的實線,並在父類的關聯末端畫一個未填充棱形。圖 12 顯示車和輪胎間的聚合關係的例子。


圖 12: 一個聚合關聯的例子

組合聚合
組合聚合關係是聚合關係的另一種形式,但是子類實例的生命週期依賴於父類實例的生命週期。在圖13中,顯示了Company類和Department類之間的組合關係,注意組合關係如聚合關係一樣繪製,不過這次菱形是被填充的。


圖 13: 一個組合關係的例子

在圖 13 中的關係建模中,一個Company類實例至少總有一個Department類實例。因爲關係是組合關係,當Company實例被移除/銷燬時,Department實例也將自動地被移除/銷燬。組合聚合的另一個重要功能是部分類只能與父類的實例相關(舉例來說,我們例子中的Company 類)。

反射關聯
現在我們已經討論了所有的關聯類型。就如你可能注意到的,我們的所有例子已經顯示了兩個不同類之間的關係。然而,類也可以使用反射關聯與它本身相關聯。起先,這可能沒有意義,但是記住,類是抽象的。圖 14 顯示一個Employee類如何通過manager / manages角色與它本身相關。當一個類關聯到它本身時,這並不意味着類的實例與它本身相關,而是類的一個實例與類的另一個實例相關。


14:一個反射關聯關係的實例

圖14:描繪的關係說明一個Employee實例可能是另外一個Employee實例的經理。然而,因爲“manages”的關係角色有%200..*的多重性描述;一個僱員可能不受任何其他僱員管理。

可見性
在面向對象的設計中,存在屬性及操作可見性的記號。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: 只顯示對象之間關係的類圖

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章