前面我們主要討論的是UML類圖,下面我們要討論的是另一種UML圖——互動圖(Interaction Diagram)。互動圖描述的是一組對象之間的互動過程,或者說,這裡我們實際上要回答這樣一個問題:“方法調用過程在UML中怎樣表示?”UML互動圖 本文將通過一個非常簡單的交易系統來說明UML互動圖。這個系統包含六個Java類。從前面幾篇文章中,我們已經知道UML類圖是分析Java程式結構的有效方法,圖一顯示了這個交易和支付系統的類圖。為了更清楚地說明各個類的職能和角色,圖一利用了前面介紹過的彩色類原型標記法。 圖一:一個簡單交易系統的UML類圖 如果我們跟蹤任意一個Java程式的執行過程,就會發現,這個過程包含了一個或者多個對類和對象的方法調用。我們通過調用對象的方法來尋求特定問題的答案或執行一個特定的動作。很多時候,被調用的方法還會調用其他方法——或者是同一對象的方法,或者是同一類的其他對象的方法,或者是其他類的對象的方法。類似地,這些被調用的方法又會繼續調用其他方法,直至問題得到了明確的答案或動作全部執行完畢(或者出現異常,這時問題將沒有答案或動作不能完成)。 UML互動圖以圖形的形式表示出方法調用過程,它有兩種形式:順序圖表(Sequence Diagram)和共同作業圖表(Collaboration Diagram)。 順序圖表 要達到某個特定的目標,必然要執行一系列的方法調用。UML順序圖表的典型用途就是顯示出方法調用過程。圖二顯示了一個交易事務中計算累計金額的順序圖表,調用從Sale類的calcTotal()方法開始,相關的代碼片斷在順序圖表之後給出。 術語說明:UML把操作(Operation)定義為方法的特徵(Signature)。“方法”(Method)這一術語被保留給實現操作的代碼。但在Java環境中,“方法”這一術語的應用範圍更廣泛一些。在UML順序圖表中,調用一個操作就叫做發送一個訊息(Message)。順序圖表實際上闡述了操作的具體實現,所以下面我們會較多地用到“方法”這個術語(偶爾也會用到“訊息”這個術語)。 圖二:計算交易總金額的順序圖表
/** 屬於Sale類: * 從lineItem的單項金額計算交易總金額 * @return 交易總額 */ public double calcTotal() { total = 0.0; Iterator i = lineItems.iterator(); while (i.hasNext()) total += ((LineItem)i.next()).calcTotal(); return total; } /** 屬於LineItem類: * 計算當前項目的交易金額 * @return 交易金額 */ public double calcTotal() { total = product.calcTotal(this); return total; } /** 屬於Product類: * 計算指定數量的產品價值多少 * @return 金額 */ public double calcTotal(LineItem li) { return amount * li.getQuantity(); } |
為了便於把握順序圖表的總體情況,圖一隻顯示了方法的名稱。詳細的順序圖表可以顯示出方法的參數和傳回值。在順序圖表中,對象以常規的UML符號顯示,即使用與對象所屬的類一樣的形狀或符號(預設是矩形),再註明對象的名稱,加上一個冒號,再加上相應的類名稱。然後再為整個名字加上底線(例如,圖二中的aProduct:Product)。可以省略對象的名字(例二中的:Sale),也可以省略類的名字(例二的Sender),但兩者都省略顯然是不允許的。如果省略了類的名字,冒號必須保留。 時間的流逝方向是從上到下的垂直方向。每一個對象有一條順著頁面垂直向下的生命線(Lifeline),緊接著表示對象的矩形。方法調用的表示方式是,畫一根從發出調用的對象的生命線指向被調用物件生命線的箭頭。只要對象的任意方法處於執行狀態,對象的生命線加寬。加寬之後的生命線稱為“活動條”(Activation Bar),活動條可以嵌套,表示在前一方法的執行過程中,又有同一對象的另一個方法被調用,圖二的getQuantity()方法示範了活動條嵌套的一個例子。 方法的傳回值可以通過虛線開叉箭頭的形式表示,但這是可選的,例二中從:Sale指向Sender的箭頭。 如果要在一個對象的集合上進行迭代操作,則在方法的名字前面加上一個星號(再在方括弧裡面說明迴圈條件,可選)。在圖二中,Sale類對LineItem類對象的調用給出了迭代操作的一個例子。 就象UML類圖一樣,原本需要查看多個原始碼檔案才能瞭解的資訊,通過一個UML順序圖表就可以表示出來。對已有的代碼實施反向工程獲得對應的順序圖表,可以協助不熟悉代碼的開發人員快速瞭解程式的工作流程。 圖三顯示了Sale類complete()方法的順序圖表,它對調用次序(訊息)進行了編號。complete()方法調用了Sale類的另外兩個方法,即calcTotal()和calcPayments()。圖三用環形的回調符號表示一個對象正在調用它自身的方法。 圖三:完成一次交易的順序圖表 如果順序圖表很大,可能出現一個螢幕無法顯示出來的情況。在圖三中,通過設定建模工具Together ControlCenter的選項面板,類的名稱不再和對象名稱並列顯示,而是顯示在對象名稱的下方,減少了顯示對象所需的水平空間。如果類的名稱很長,用這種顯示方式可以有效地縮減圖形寬度,一般能夠改善圖形的可讀性。然而,如果要嚴格遵從最新的UML規範,類的名稱必須和對象名稱並列放置,中間用冒號分隔,二所示。 complete()方法調用了calcTotal()方法,圖二顯示的calcTotal()序列是圖三complete()序列的結果。如果要簡化圖三,我們可以省略圖三的Product對象以及它與LineItem對象的互動,讓讀者在查看這部分內容時參考圖二。和類圖中面臨的細節處理問題一樣,到底是否要省略(或者說,詳細到哪種程度),也必鬚根據使用者的需要而定。例如,一些順序圖表的讀者可能希望註明各種標準的Java類,例如迭代器、封裝器、集合類等。雖然順序圖表可以顯示出要用到的迴圈和分支結構,但通常而言,這一層次的細節最好讓讀者在順序圖表的指導下通過閱讀Java原始碼獲得。 圖四是利用Together ControlCenter對Sale類的complete()實施反向工程,並要求它給出所有細節資訊所得到的順序圖表。對於大多數人來說,這裡的細節資訊可能太多了一點。但是,圖四也說明了一個問題,正如exception對象所顯示的:在序列執行期間建立的對象畫在它被建立的位置,而不是順序圖表的頂端。 圖四:利用工具產生的詳細順序圖表 就象我們在討論類圖時遇到的情況一樣,UML規範為順序圖表也提供了大量有細微差別的符號,不過本文說明的符號已經足以讓你入門了。 共同作業圖表 UML互動圖的另一種形式是共同作業圖表(Collaboration Diagram)。共同作業圖表和順序圖表在語義上相同,但共同作業圖表排列對象的方式比較自由,完全由繪圖者的喜好決定。在共同作業圖表中,互動動作的次序由訊息的編號決定。一些人偏愛這種繪圖方式,許多功能比較完善的UML工具允許使用者將一個圖在共同作業圖表符號和順序圖表符號之間來迴轉換。一些開發人員建議,用共同作業圖表來顯示組件之間的互動過程,用順序圖表來顯示組件內部各個類的互動過程。圖五顯示的共同作業圖表等價於圖二顯示的順序圖表,圖六的共同作業圖表和圖四的順序圖表一樣。 圖五:與圖二等價的共同作業圖表圖六:與圖四等價的共同作業圖表 結束語:在實踐中,許多必需的互動序列可以隱含在類圖之中,特別是類圖用類原型和Stereotype來表示特定的行為和互動模式之時。UML互動圖把原本隱含的互動過程明確地表達出來,同時也明確地說明了原本在類圖中不明確的互動過程。換句話說,UML互動圖是對傾向於描述靜態特徵的類圖的補充,使得對象的動態互動過程明確化。 |