< DOCTYPE html PUBLIC -WCDTD XHTML StrictEN httpwwwworgTRxhtmlDTDxhtml-strictdtd>
本文從Java程式員的角度闡述UML和對象模組化問題,是一個深入淺出的實用性介紹。雖然從曆史和基本理念方面來探讨UML非常吸引人,但我們還是直接從Java代碼開始,看看UML如何描述Java類,再在叙述過程中插入一些曆史和基本理念方面的知識。
UML類圖
在Java中,我們用下面的代碼聲明兩個公用類,每一個Java類放入一個檔案,檔案的名字就是Java類的名字加上擴充名.java:
public class Person{}
public class Organization{}
UML是Unified Modeling Language的縮寫,即“統一模組化語言”。與Java不同,UML是一種圖形化的模組化“語言”,它用一個矩形來表示一個類,在矩形的内部寫上類的名稱,一個類圖可以放入多個類。用矩形表示類,是UML中U(Unified)起的作用。在UML的第一個版本出現,每一個對象模組化專家都有自己的一套符号,一些人用點表示類,一些人用圓圈表示類,還有一些人用圓角矩形表示類。顯然,這很容易引起混亂。後來,Rational公司的三個專家——Grady Booch、James Raumbaugh、Ivar Jacobson達成了一緻意見,同意“統一”他們各自使用的符号,UML終于創立,符号之争也終于落下了帷幕。圖一就是上面兩個Java類的UML類圖:
圖一:有二個類的簡單類圖
如果要描述一系列類的内部結構以及它們互相之間的關系,UML類圖是非常有用的。例如,在許多書籍中,我們可以看到作者用類圖來描述各個類之間的關系。
顯然,空的類沒有什麼實際意義。我們要為Person類加上一些執行個體變量和簡單的方法。下面是Person類的代碼,已經過簡化處理,不含任何注釋:
public class Person {
private String name;
private String socialSecurityNumber;
private Date dateOfBirth;
private String emailAddress;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSocialSecurityNumber() { return socialSecurityNumber; }
public void setSocialSecurityNumber(String socialSecurityNumber)
{ this.socialSecurityNumber = socialSecurityNumber; }
public Date getDateOfBirth() { return dateOfBirth; }
public void setDateOfBirth(Date dateOfBirth) { this.dateOfBirth = dateOfBirth; }
public int calcAgeInYears() {return 0;}
}
圖二顯示了Person類的UML圖。可以看到,UML用“+”和“-”符号分别表示public和private修飾符。UML隻顯示操作和屬性類型之類的特征資訊,操作的結果在行未的冒号之後聲明。
圖二:在UML類圖中描述屬性和方法
由于UML類圖不包含方法的具體實作,是以在UML類圖中檢視屬性和方法等基本資訊要比直接檢視Java源代碼更友善一些。在建立UML圖時,人們常常忽略或隐藏各種細節資訊,以便檢視和掌握類的整體結構。例如,UML類圖常常隻顯示出屬性和操作的名稱,簡單的通路器方法(諸如getXXX()、setXXX()之類的方法)也常常不顯示出來。圖三就是簡化圖二得到的結果。
圖三:經過簡化的Person類UML圖
圖三清楚地顯示出了Person類主要的屬性和方法。但是,單個類的UML圖還不是很有用。隻有包含多個類且描述了多個類之間關系的UML圖,才具有實用意義。UML用兩個類之間的連線來表示兩者之間的關系,不同的線型表示不同的關系,在UML類圖中最常見的關系是關聯關系。
關聯關系
前面Person類的屬性都是簡單類型(Primitive Type),或者說是Java直接提供的标準類型。現在來考慮下面的代碼片斷,它增加了一個對Organization執行個體的引用:
...
private Organization employer;
引用的名稱是employer,意味着這裡的Organization代表着Person的雇主。圖四顯示了如何在UML中描述這種關系:
圖四:兩個類之間的關聯關系
兩個類之間的連線表示Person類對Organization類有一種依賴關系。這條線是一條實線(而不是虛線),表示這種依賴關系是一種關聯。
如有必要,關聯關系可顯示出角色、多重性、關聯方向等屬性。圖四的關聯關系顯示出Organization對象在該關系中是雇主的角色,“0..1”表示每一個Person類的對象最多和一個Organization類的對象有關系,也可能和0個Organization對象有關系(即Person對Organization的引用可設定為null)。開叉的箭頭表示Person類擁有對Organization的引用,而不是Organization擁有對Person的引用。
多重性
多重性回答這樣一個問題:在一個關系中,每個類各有多少對象參與其中?常見的多重性如圖五所示。
圖五:常見的多重性及其含義
前面我們已經看到了Java代碼中0..1多重性的執行個體。不難猜測,多重性為“1”意味着一個類對另一個類的引用不能為null(一般是這樣一種情形:引用的值在構造函數中初始化,且在所有相關的set方法中禁止把該引用設定為null)。
值為“1..*”和“0..*”的多重性稍微複雜一點。在Java中,實作這類多重性的途徑之一是使用某種集合類,例如Vector,來儲存可能需要用到的多個引用:
ClassA
{
...
Vector classB; // 儲存B類對象引用的Vector
對于“1..*”多重性,Java程式必須確定Vector至少包含一項内容。
在有些關系中,多重性的值可以是某個精确的範圍或數字。例如,一個小孩最多有兩個生物學意義上的健在雙親,即它的多重性可表示為“0..2”。用Java代碼描述這種關系時,程式必須帶有確定Parent對象執行個體少于或等于2個的限制。
一個UML關聯加上多重性、角色、關聯方向之後,能夠描述出大量資訊,遠比一大堆Java源代碼簡潔和直覺。雖然UML圖沒有說明關系的具體實作方式,但它能夠充分地說明關系的意義和作用。圖六顯示了标注多重性、角色名稱之後的雇傭關系,它表示一個Person可以為多個Organization工作,一個Organization可以雇傭多個Person。
圖六:雙向關聯關系
聚合與合成
關聯隻是UML中的關系之一。下面我們來看看UML中的其他兩種關系——聚合(Aggregation)和合成(Composition),它們實際上是關聯關系的不同變種。聚合是這樣一種關聯關系,在這種關系中一個類的對象代表着另一個類的對象的一部分,有的人是以也把聚合關系叫做“全體-部分”關系。聚合關系用實線空心菱形箭頭表示,箭頭由表示Part的類指向表示Whole的類,參見圖七。
圖七:聚合與合成
那麼,在Java程式中聚合關系又是什麼樣的呢?答案是:這要看你在問誰。聚合是一個有争議的概念,表達的是一種生命周期依賴關系。有人根據習慣認為,聚合意味着Whole類必須負責建立和拆除Part類的對象;但也有人為聚合關系下了更寬松的定義。到底應該怎麼了解,你最好能夠在合作者之間取得一緻意見和約定,避免混淆。
合成是一種較強的聚合關系。這兩種關系基本相似,不同之處在于,在合成關系中,Part的對象任何時候隻能從屬于一個Whole對象,也就是說,必須用Java代碼確定這種唯一的從屬關系。
前面我們已經看到,類的屬性、操作以及各個類之間的關系可以用UML類圖來描述。然而,對于Java類裡面的對象引用,什麼時候應該把它當作關聯關系、什麼時候把它當作屬性,這一點還沒有搞清楚。答案是:要在哪一個層次交流資訊,UML圖就應該具體到哪一個層次。有些時候,即使是簡單的對象,也最好畫出它的類圖,把其他類對它的引用描述成關聯關系;另一些時候,可能需要把對象引用表示成屬性,甚至從類圖完全省略對該對象的引用,以便在類圖中突出顯示其他更重要的類和關系。大多數的UML工具軟體都提供了隐藏UML類圖各種細節資訊的機制。
獲得UML圖一般有兩種辦法,手工設計UML圖(在此基礎上可由UML工具生成Java應用的骨架代碼),或者用工具分析Java源代碼(甚至位元組碼)獲得UML圖。一些優秀的UML工具能夠在你繪制UML圖的同時生成Java代碼,在你編輯Java代碼的同時更新UML圖。例如TogetherSoft的Together ControlCentre,本文的UML圖就是用這個工具繪制的,有免費版Together Community Edition可供試用。
結束語:本文就到這裡結束。在下一篇文章中,我們将分析如何在UML中表示Java的兩個重要概念:繼承,接口。
本文轉自 netcorner 部落格園部落格,原文連結:http://www.cnblogs.com/netcorner/archive/2007/12/05/2912245.html ,如需轉載請自行聯系原作者