概念: 結構化類別
結構化類別是指由具有明確「巢狀」觀念的組件所組成的類別,可用來塑造「包含階層」,這些階層是一些由「組件」構成的類別。
關係
相關元素
主要說明

定義

根據 UML ([UML04]),「類別」是 EncapsulatedClassifier 與 Meta 類別 Class(讓「類別」可以有內部結構和埠)的子類型。此外,UML 也將元件定義為「類別」的子類型。因此,在 RUP 環境中,我們將元件類別都視為結構化類別。

組件

結構化類別的一個實例包含一個物件或一群對應於各組件的物件。當包含的結構化類別實例銷毀時,這些實例也會全數銷毀。

下列範例顯示 Car 類別的兩個可能的觀點:

在圖 (a),Car 與類別 Wheel 之間具有角色名稱為 rear 的組合關聯,與類別 Engine 之間具有角色名稱為 e 的組合關聯。類別 Engine 的任何實例可連結至類別 Wheel 的任意實例個數。

在圖 (b),規格相同。不過,圖 (b) 另外又指定:

  • reare 屬於類別 Car 的內部結構。這樣可以針對類別 Car 環境內的 WheelEngine 類別的實例來指定詳細資料,但不適用於一般的輪子引擎

  • 在類別 Car 環境之內,扮演 e 角色的實例只能連接兩個扮演 rear 角色的實例。此外,扮演 erear 角色的實例也必須是類別 Car 上相同實例的角色時,才能連結。

  • 換句話說,類別 WheelEngine 的實例在類別 Car 的實例內各自扮演角色時會有其他限制。一般的 WheelEngine 實例不受這些限制。如圖 (a) 所示,其他輪子引擎可能任意連結。

圖解說明詳見隨附的文字。

範例:在結構化類別內各自扮演角色的組件

連接器

連接器是一個結構化類別中兩個組件之間的關係實例。是一個可用來通訊的鏈結。連接器可由一般關聯或暫時性關係來實作,例如程序參數、變數、整體值或其他機制。

結構化類別的內部「佈線」由組合連接器和委派連接器來指定:

  • 在結構化類別的實作內,組合連接器可連接不同組件的埠。從一個結構化類別的一個埠送出的訊息,由另一個結構化類別的連接埠來接收。一群組件可透過埠串接起來。一個組件除了知道其他組件存在且滿足連接埠的限制,可以完全不必瞭解其他任何細節。結構化類別之間的通訊是利用埠來塑造模型。


  • 委派連接器可連接結構化類別的外接埠和其中一個內部組件的埠。外接埠收到的訊息會傳送至內部組件的埠;內接埠送出的訊息會傳送至外接埠,再送至連接的結構化類別。

埠是結構化類別的一項結構特性。在來自結構化類別外部並穿過埠的通訊活動上,強制規定遵守已宣告的介面,可以提高封裝性,讓結構化類別的規格和互連性更精準。

埠的需求介面和供應介面指定通過此互動點的互動作業所需的一切。如果一個結構化類別和環境之間的所有互動皆透過埠來完成,即表示該結構化類別的內部和周遭環境完全隔離。如此一來,只要環境滿足埠所指定的限制,結構化類別可用於任何環境。

埠的實作沒有任何預設的作法。可能實作為明確物件,或只是實作中隱含的虛擬概念。

以下提供埠的範例:

範例 1

圖解說明詳見隨附的文字。

Car 和 Boat 使用之 Engine 的埠

上圖顯示類別 Engine 有一個埠 p 和兩個介面:

  • 供應介面 powertrain,指定引擎在這個埠提供的服務 (亦即,到達此埠的通訊可存取的操作和接待動作)。
  • 需求介面 power,指定引擎期待環境提供的服務。

在埠 p 上,Engine 類別完全封裝;可以直接指定,不需瞭解引擎的裝配環境。只要環境符合引擎的供應介面或需求介面所規定的限制,引擎即可正常運作。

舉例說明,本範例顯示 Engine 類別的兩種用途:

  • Car 類別透過 axle(輪軸)將引擎的埠 p 連接到一組輪子。
  • Boat 類別透過 shaft(螺旋槳軸)將引擎的埠 p 連接至螺旋槳。

不論是汽車引擎或輪船引擎,只要 Engine 和連接至埠 p 的組件之間的互動符合供應介面和需求介面的限制,引擎就會依規定運作。

再者,即使 Engine 有其他已宣告的埠,例如 Fuel Consumption 的埠 f,汽車的輪子和輪船的螺旋槳一樣會透過埠 p 來存取 Engine。不論使用何種燃料及汽車和輪船安裝何種燃油錶,埠 f 很可能就是燃油錶。

範例 2

這個埠範例以 Java Logging API ([JAV03]) 為基礎,此套件提供下列 Java 2 平台核心記載機能的類別和介面:

  • Logger 是應用程式執行記載呼叫的主要實體。適用於記載特定系統或應用程式元件的訊息。
  • Level 指出日誌訊息的重要性和緊急性。
  • Filter 精確控制要記載什麼,大於記載層次提供的控制
  • Handler 取得 Logger 的訊息,並匯出至不同的目的地(記憶體、輸出串流、主控台、檔案及 Socket)
  • Formatter 提供日誌記錄的格式化支援

這些類別和介面涉及兩種重要的合作類型。有些類別和介面用於寫入日誌,有些用於管理日誌。下圖顯示用戶端和管理者在日誌上的兩種不同的合作關係,以 UML 合作模型來表達:

  • Writing 合作,LogClient 角色連接 LogWriter 角色來寫入日誌。
  • Administration 合作,LogAdministrator 角色連接 LogController 角色來存取日誌和變更日誌設定。

圖解說明詳見隨附的文字。

用戶端和管理者在日誌上的不同合作關係

塑造記載服務及其合作關係時,有一種可能的 UML 2.0 表示法是利用具有埠且宣告介面的元件,如下圖所示:

圖解說明詳見隨附的文字。

以供應介面組成多個埠的元件所實作的 Java Logging API 套件

在 Java Logging API 規格中,有些記載服務實作為類別,有些實作為介面。在此範例中,我們將每一項服務塑造成供應介面,這些介面由元件內部的組件來實現。在邏輯上組成多個埠的介面,可以表達上述 WritingAdministration 合作相關的兩種不同的行為。因此,我們將:

  • LoggerLevel 介面組成 LogWriter 埠。日誌用戶端可存取這些介面來寫入日誌。
  • HandlerFilterFormatter 介面組成 LogController 埠。日誌管理者可透過這些介面來存取日誌和變更日誌設定。

此建模方案在邏輯上將介面組成不同的埠,達到各司其職的目標。我們可以更準確控制元件的規格,以及元件和外界的互連性。

建模

在設計期間,類別和元件可拆解為相連組件的集合,這些集合可再進一步拆解。

組合結構圖可用來顯示結構化類別的分解。舉例說明,下圖顯示售票系統的售票處組合結構圖。此類別拆解為三個組件:

  • 售票員介面
  • 一個演出簡介,根據日期和其他準則擷取演出資料
  • 一組資料庫,包含演出和門票的資料。

各組件透過埠所規定的明確介面來互動。整個售票處只透過一個埠與外界互動。在此埠的訊息會分派至售票員類別,但外界用戶端看不到售票處的內部結構。

圖解說明詳見隨附的文字。

範例:售票系統的組合結構圖。

UML 1.x 表示法

請注意,「結構化類別」在 UML 2.0 中是新的概念。

RUP 定義的「封裝體」大多可用「結構化類別」來表達(如需本主題的相關資訊,請參閱工作成果:封裝體工作成果準則:封裝體。)

如果您的工具僅支援 UML 1.5,請另外參考工作成果:封裝體工作成果準則:封裝體中討論的替代表示法。

如需相關資訊,請參閱UML 1.x 和 UML 2.0 的差異