第13章 術 語 大 全 (1)

1. abstract(抽象)
  抽象是不能被直接實例化的類、用例、信號、其他類元或其他泛化元素,它也可以用來描述沒有實現的操作。反義詞:concrete。
  見abstract operation,generalizable element。
語義
  抽象類是不可被實例化的類,即它可以沒有直接實例,這既可能是因爲它的描述是不完整的(如缺少一個或多個操作的方法),也可能是因爲即使它的描述是完整的它也不想被實例化。抽象類是爲了以後說明。抽象類必須有可能含有實例的後代才能使用,一個抽象的葉類是沒用的(它可以作爲葉在框架中出現,但是最終它必須被說明)。
  具體類可以沒有任何抽象操作(否則,它必爲抽象的),但是抽象類可以有具體操作。具體操作是可以被實現一次並在所有子類中不變地使用的操作。在它們的實現中,具體操作可以只使用聲明它們的類所知道的特徵(屬性和操作)。繼承的目的之一即將這些操作在抽象的超類中分解以使得它們可以被所有的子類分享。一個具體操作可以是多態的,即後代類中的方法優先於它,但是它也可以不必是多態的,它可以是一個葉操作。一個所有操作都被實現的類可以是抽象的,但是這一點必須被明確聲明。一個有着一個或多個未實現操作的類自然是抽象的。
  同樣的語義也適用於用例。抽象的用例定義了行爲的片斷,這個行爲自己不能出現,但是它可以通過泛化、包括或擴展關係在具體用例的定義中出現。通過在抽象的用例中分解公用的行爲,模型變得更小和易於理解。
  類似的關係也存在於其他的類元和泛化元素中。
表示法
  抽象類或抽象操作的名字用斜體字表示。關鍵字abstract可以放置在位於名稱下面或後面的特性表中,如Account{abstract}。
見class name。
示例
圖13-1表示一個抽象類Account,它有一個抽象操作computeinterest和一個具體操作deposite。兩個具體子類已經被聲明瞭。因爲子類是具體的,所以它們每一個必須實現操作computeinterest。屬性總是具體的。
13-1.gif
圖13-1 抽象和具體的類
討論
  將一個類建模成抽象的或具體的,其間的差別並不像它第一次出現時那麼清晰和基本。它更像有關模型的設計結果而不是繼承特性。在設計的發展過程中,類的狀態可能發生變化。如果將列舉出所有可能性的子類加入到具體類中,那麼這個具體類可以建模成抽象的。如果子類之間的差別被認爲是不必要的且被刪除,或者這些差別用屬性值而不是用不同的子類表示,那麼這個抽象類可以建模成具體的。
  簡化決定的方法之一是採納以下設計準則:所有的非葉類必須是抽象的(除了某些爲了以後說明的抽象葉類外,所有的葉類必須是具體的)。這並不是UML的規則,它既可以被採用也可以不被採用,設計這個"抽象超類"規則的原因是超類上可繼承的方法和具體類上的方法經常有不同的需求,這種需求並不能被單個方法很好地實現。超類中的方法被迫做兩種事:定義能被所有後代觀察到的通用例子和爲特定類實現通用例子。但是這兩個目標經常發生衝突。相反,一個非抽象的超類能被機械地分離到一個抽象的超類和一個具體的葉子類中。抽象的超類包含被所有子類繼承的方法;具體的子類包含所有特定的可實例化類要求的方法。在抽象的超類規則後也允許在保持特定具體類型的變量或參數與保持着超類的任何後代的變量或參數之間存在完全的區別。
13-2.gif
圖13-2 具體的超類產生的模糊性
在圖13-2中,考慮類letter的聲明,它並沒有遵循抽象超類規則。該類有一個getNextSentence操作,它返回下一個還沒有讀的句子的明文,還有resetCursor操作,它將鼠標置回開始處。而子類EncryptedLetter表示已經被加密的字母。操作getNextSentence重載被重載因爲明文在被返回前必須要解密。操作的實現完全不同的。因爲Letter是一個具體超類,所以(非重載)是不可能的。普通Letter類或EncryptedLetter子類中。
抽象超類方法用於辨別抽象類Letter(它既可能是加密的字母,也可能是未加密的字母)並且加入類NonEncrypedLetter以表示具體例子,如圖13-3。在這個例子中,getNextSentence是一個被每個子類實現的抽象操作,resetCursor是一個在所有子類中相同的具體操作。這個模型是對稱的。
如果遵循抽象類規則,那麼抽象類聲明能從類層次中自動確定,並且在圖中表示它也是多餘的。
聲明一個抽象葉類一般是沒用的,但有一個例外:當抽象類作爲一組全局類作用域的屬性和操作的通用命名空間時可以被聲明。這種情況較少,大部分用於處理非面嚮對象語言的編程時,建議用戶在大多數情況下不要用它。全局值通過引用全局依賴關係違反了面向對象設計的精神。單實例類可以以更擴展的方式提供同樣的功能(可參見[Gamma-95])。
13-3.gif
圖13-3 抽象超類避免模糊性

2. abstract class(抽象類)
抽象類是可能不會被實例化的類。
見abstract。
語義
抽象類可能沒有直接實例,可能有間接實例(通過它的具體後代)。
見 abstract 的討論。
3. abstract operation(抽象操作)
抽象操作缺少實現,即它只有說明而沒有方法。實現必須被具體後代類補充。
見abstract,generalizable,inheritance,polymorphic。
語義
如果一個操作在類中被聲明爲抽象的,那麼該操作缺少在類中的實現,且類本身也必須是抽象的。操作的實現必須由具體的後代來滿足。如果類繼承了一個操作的實現但是將操作聲明是抽象的,那麼抽象的聲明就使類中被繼承的方法無效。如果一個操作在類中被聲明是具體的,那麼類必須滿足或繼承從祖先那裏得到的實現,這個實現可能是一個方法或調用事件。如果操作在類中根本沒有被聲明,那麼類繼承從它的祖先那裏得到的操作聲明和實現。
操作可以作爲方法或由調用事件觸發的狀態機轉化而實現。每個類可以聲明它自己的方法、操作的調用事件或者繼承祖先的定義。
表示法
抽象操作的名稱用斜體字表示,如圖13-4,而關鍵字abstract可以放在操作特徵標記後的特性表裏

13-4.gif圖13-4
討論
繼承概念的最大用途是支持能被每個具體後代類有區別地實現的抽象操作。抽象操作允許調用者在不知道哪個對象的類是目標的情況下使用操作(假設目標對象通過作爲一個抽象類的間接實例支持這個操作,並且這個抽象類有抽象操作的聲明)。這種多態操作的重要性在於,決定對象種類的職責從調用者轉換到了繼承機制。不僅調用者不會有寫例子聲明的麻煩和代價,並且調用者也不必關心抽象類的哪個子類會存在。這意味着附加子類將與新的操作實現一起被加入。因此,抽象操作、多態和繼承在不必改變使調普通行爲代碼的情況下,通過加入新的對象和行爲促進系統的升級。這大大減少了系統升級的時間,更重要的是,它降低了偶然的不協調的可能性。
4. abstraction(抽象)
抽象是確認一件事物本質特徵的行爲,這種行爲將這個事物與其他所有事物區分開來。 抽象涉及到通過觀察幾組事物的本質公共特性來查找它們的共同點。抽象往往涉及到觀察者的觀點和目的;不同的目的導致同一事情的不同抽象。所用的建模過程都涉及到抽象,通常存在與不同目的的不同層次上。
抽象是一種將不同層次上的同一概念的兩種元素聯繫起來的依賴關係。
見派生、實現、精化、跟蹤。
語義
抽象依賴關係是不同抽象層上的兩個元素之間的關係,比如在不同模型中、不同準確度上、不同具體性上或不同優化層中的描述。通常,兩個描述不會被同時用到。正常情況下,一個元素比另一個更詳細一些,客戶元素比提供者元素更詳細。如果不明確哪個元素更詳細,那麼兩個元素都可以建模成客戶。
抽象依賴關係的構造型是跟蹤(關鍵字trace)、精化(關鍵字refine)、實現(關鍵字realize)和導出(關鍵字derive)。
表示法
抽象依賴關係表示成從客戶元素指向提供者元素的箭頭,並附有關鍵字《trace》、《refine》或《derive》。實現依賴關係有它自己特殊的表示符號,表示成指向提供者元素的有着封閉三角形的虛線箭頭。
元素之間的映射可以作爲約束附加在關係上。
標準元素
derive,refine,trace。
5. access(訪問)
訪問是一種許可依賴關係,允許一個包引用另一個包中的元素。
見friend、import、visibility。
語義
一個包(客戶)如果要引用另一個包(提供者)內的元素,那麼它必須引入一個包,該包包括客戶包到提供者包的《access》或《import》依賴關係上的元素。一個包可以隱含地獲得對由包含該包的任何包所引入的包的訪問權(即,嵌套包可以看到包含包可以看到的一切)。
包中的元素可以訪問包內所有可見的元素。可見性規則可以總結如下:
* 一個包中定義的元素在同一個包中是可見的。
* 如果一個元素在一個包中是可見的,那麼它對所有嵌套在這個包中的所有包都是可見的。
* 如果一個包訪問或引入另一個包,那麼在要被引入或訪問的包中定義爲公共可見性的元素對引入包都是可見的。
* 如果一個包是另一個包的孩子,那麼所有在父包中定義爲公共的或受保護的可見性的元素對子包是可見的。
* 訪問或引入依賴關係是不能傳遞的,如果A能看到B,且B能看到C,這並不意味着A能看到C。
結論:除非一個包能夠訪問它的嵌套包且嵌套包的內容是公共可見的,否則這個包不能看到它自己的嵌套包的內部。
下面是有關可見性的更深一步的規則:
* 如果一個類元的內容,如它的屬性和操作以及嵌套類,在類元中具有公共可見性,那麼它們在包中是可見的。請注意一個子系統的未組織的內容是由上面提到的包規則指導的,但是任何子系統本身的屬性或操作由這條規則指導。
* 如果一個類元的內容有公共的或受保護的可見性,那麼它們對後代類元是可見的。
* 一個類元的所有內容對類元內的元素都是可見的,包括類元的方法或狀態機中的元素。
一般情況下都會涉及到對等包中的元素。在這種情況下,一個元素能看到它自己包內的所有元素和被它所在包引入的包的具有公共可見性的所有元素。一個類可以看到其他類中的公共特徵。一個類也可以看到它的祖先的受保護的特徵。
表示法
訪問依賴關係用一個從客戶包指向提供者包的虛箭頭表示。箭頭用關鍵字《access》作爲標號。
討論
圖13-5爲一個兩個包間的對等層訪問的例子。包P能夠訪問包Q,但是包Q不能訪問包P。P包中的類K和L能看到包Q中的類M,但是它們看不到私有類N。除了具有公共可見性的類K之外,類M和N看不到包P中的任何類,因爲包Q不能訪問包P。要想一個類對對等包是可見的,這個類必須具有公共可見性,並且它的包必須被對等包訪問或引入。
13-5.gif
圖13-5 對等訪問
13-6.gif
圖13-6 訪問規則
圖13-6爲一個有關可見性和訪問聲明的更復雜的例子。元素名字前的符號代表了它的可見性:+代表公共的,#代表是受保護的(只對後代可見),-代表是私有的(對外界是不可見的)。
類A能看到C和E因爲它們包含在包Y和X內。
類C和A能夠看到D,因爲包Y引入了包Z。類A嵌套在包Y中並且能夠看到Y能看到的一切。
類A、C和E能看到B,因爲它們嵌套在包X中,而X引入包含B的包V,但是,它們看不到F,因爲F在它的包V中是有私有可見性。所以,類F在包V外是看不到的。
類E看不到D因爲D在包Z中,而Z並沒有被包X訪問。
類C和E都看不到A。類A在包U中,U沒有被任何包訪問。
類B和F能夠看到類D和E,D和E建立在包含包中。它們也能看到C,C在包Y中,而包Y被包含包訪問。雖然F是私有的,但這並不影響它看到其他的類,而其他的類看不到F。
類B和F能夠互相看到,因爲它們在同一個包中。類F對外面的包中的類是私有的,但對它自己包中的類不是這樣。
6. action(動作)
動作是可執行的原子計算,它導致模型狀態的改變和返回值。對比:activity。
見entry action,exit action,transition。
語義
動作是一個原子計算,即它不會從外界中斷。動作可以附屬於狀態機中的轉換(在兩個狀態之間或在一個狀態中)或交互中的某一步。通常,它是一個的或近似原始的在系統狀態的操作,也常常位於一個獨立對象的狀態上。典型動作有分配屬性值、訪問屬性或鏈接的值、創建新的對象或鏈接、簡單算法和向別的對象發送信號。動作是行爲建立之外的步驟,動作的意思是指"快速"計算,以使得系統的反應時間不會被減少。系統可以同時執行幾個動作,但是動作的執行應該是獨立的。
動作也可以附屬於轉換,當轉換被激發時動作被執行。它們也可以作爲狀態的入口動作和出口動作出現。這些動作由進入或離開狀態的轉換觸發。所有動作都是原子的,即它們執行時完全不會被別的動作所幹擾。
活動也是一種計算,但是它可以有內部結構並且會被外部事件的轉換中斷,所以活動只能附屬於狀態中,不能附屬於轉換。與動作不同,雖然活動自己也能中斷,但是如果外界不中斷它,它可以無限期地持續下去。而動作則不能從外部中斷並且可以附屬於轉換或狀態的入口或出口,而非狀態本身。
結構
動作包括一個目標對象集合、一個對將要被髮送的信號或將要被執行的動作的引用(即請求)、一張參量值表和一個可選的用於指明迭代的遞歸表達式。
* 對象集合。對象集合表達式產生一個對象的集合。在許多情況下,這個集合包含一個獨立的固定的對象。有給定參量表的消息拷貝被同時發送到集合中的每個對象,即廣播到每個對象。每個目標獨立接收和處理消息的單獨的實例。如果集合是空的,那麼什麼都不會發生。
* 請求。指明一個信號或聲明一個操作。信號被髮送到對象,操作被調用(對於具有返回值的操作,對象集合必須包含一個對象)。
* 參量表。參量列表。當賦值的時候,參量表中的值必須與信號或操作的參數相一致。參量被作爲發送或調用的一部分。
* 再發生。一個迭代表達式,說明需要執行多少次動作,並指定迭代變量(可選)。這個表達式也可以描述一個條件動作(即進行一次或不進行)。
幾種動作
* 賦值動作。賦值動作將一個對象的屬性值設置定爲給定值。該動作包含一個對目標對象的表達式、對象屬性的名字和一個被分配到對象內屬性槽的值的表達式。
* 調用動作。調用動作導致一個對象上操作的發生,即該對象上操作的調用。該動作包含一個消息名、一張參量表達式的表和一個目標對象集合表達式。目標可能是一個對象集合。在這種情況下,調用同時發生並且操作不會有返回值。如果操作有了返回值,那麼它必須有一個對象作爲目標。
調用動作是同步的。調用者在再次接收控制之前等待被調用操作的完成。如果操作被作爲調用事件實現,那麼調用者在再次接收控制之前一直等待,直到接收者執行被調用觸發的轉換。如果操作的執行返回了值,那麼調用者在它再次接收到控制時接受了這些值。
* 創建動作。創建動作導致了對象的實例化和初始化(見Creation)。該動作包含一個對類的引用和一個可選的帶有參量表的類作用域操作。動作的執行創建了一個類的新的實例,其屬性值從計算它們的初始值表達式中得到。如果一個明確的創建動作被給定,那麼它將被執行。操作常常會用創建動作的參量值覆蓋屬性值的初始值。
* 銷燬動作。銷燬動作導致目標對象的銷燬,該動作有一個針對對象的表達式。銷燬動作沒有其他的參量。執行該動作的結果是銷燬對象及到它的所有鏈接及所有組成部分(見composition)。
* 返回動作。返回動作導致了一個到操作調用者的控制轉換。該動作只允許在被調用使用的操作中存在。該動作包含一個可選的返回值表,當調用者接收到控制時該表對調用者是有效的。如果包含的操作被異步使用,那麼調用者必須明確地選擇返回消息(作爲一個信號),否則它將會遺失。
* 發送動作。發送動作創建了一個信號實例並且用通過計算動作中的參量表達式得到的自變量初始化這個信號實例。信號被送到對象集合裏的對象,這些對象通過計算動作中的目標表達式而得到。每一個對象接收它自己的信號拷貝。發送者保持它自己的控制線程和收益,且發送信號是異步的。該動作包含信號的名稱、一張信號參量表達式表和對目標對象的對象集合表達式。
如果對象集合被遺漏,那麼信號被髮送到由信號和系統配置決定的一個或多個對象。例如,一個異常被髮送到由系統策略決定的包含作用域。
* 終止動作。終止動作引起某種對象的銷燬,這個對象擁有包含該動作的狀態機,即該動作是一種"自殺"行爲。其他對象會對對象的銷燬事件做出反應。
* 無解釋動作。無解釋動作,一種控制構造或其他構造的動作。
表示法
UML沒有一種固定的動作語言,它希望建模者使用一種實際的編程語言去編寫動作。下面對OCL的改編是爲了寫動作僞代碼,但這並不是標準的一部分。
賦值動作
target:=expression
調用動作
object-set.operation-mane(argrment list,)
創建動作
new class-name(argument list ,)
銷燬動作
object.destroy()
返回動作
return expression list ,
發送動作
object-set.signa-name(argument list,)
終止動作
terminate
無解釋動作
if (expression) then (action) else (action)
如果需要明確區別調用與發送,關鍵字call和send可以作爲表達式的前綴,它們是可選的。
討論
UML 規格說明定義了一組動作,同時也說明在實際實現中可以用支持工具加入其他動作。這個決定是爲了平衡精確性需求和開發者使用多種具有很廣泛語義概念的目標語言的需要。編程語言的執行語義的變體要比數據結構和有用的控制構造集合中的變體多。不考慮理論上的可行性,微小的區別很難在語言中與實際的方式對應上。選擇一種編程語言作爲動作語言的基礎會降低別的語言的作用,且動作的語義會留下一些不完整性和二義性,而這也是我們所不希望的。如果想使語義更準確些,UML必須與一種動作語言相結合。有些批評者說因爲UML太自由了,所以它並不精確,但是它的不精確程度不會超過它所選擇的動作語言的不精確程度。UML的真正缺陷是它沒有實現動作和其他表達式的多語言表示,但是在今天的多語言世界上這幾乎是不可能的。
7. action expression(動作表達式)
動作表達式是決定動作或動作順序的表達式。
討論
UML並沒有說明一個動作表達式的語法結構,由支持工具來負責這項工作。我們希望不同的使用者可以用編程語言、僞符號,甚至自然語言來表示動作。更精確的語義需要詳細的設計,這也是許多用戶會用到實際編程語言的地方。
8. action sequence(動作順序)
動作順序是被連續執行的一組動作,它是動作的一種。
語義
動作順序是一組動作,這些動作被連續地執行。整個序列被看作是一個原子單元,即它不能被中斷。動作順序即一種動作,故也可以被附加到轉換和交互。
表示法
動作順序用一個字符串表示,包含一系列由分號分隔開的動作。
如果動作用一種特定的編程語言表示,那麼動作對聲明序列的語法可以被替代使用。
示例
count:=0;reservations.clear();send kiosk.firstScreen()
9. action state(動作狀態)
動作狀態的用途是執行動作並轉換到另一個狀態。
見activity state,completion transition。
語義
動作狀態的目的是執行一個入口動作,在這之後進行向另一個狀態的完成轉換。動作狀態是原子的,即它不能被外部事件的轉換中斷。從理論上講,它表示一個可以在忽略不計的時間內完成並不與同時發生的其他動作相互作用的計算。而實際上,它需要時間來執行,但是時間要比可能發生事件需要的反應時間要短。它不能有由事件觸發的轉換。動作狀態沒有子結構、內部轉換或內部活動。它是一種啞狀態,可用於把狀態機組織成邏輯結構。它通常有一個輸出的完成轉換。如果有監護條件,則可能有多種輸出的完成轉換,所以也代表了一個分支。
表示法
動作狀態並沒有特殊的表示符號。它可以表示爲具有入口動作的原始狀態,也可以表示爲一個活動狀態。
10. activation(激活)
激活是操作的執行。激活(也叫做控制期)表示一個對象直接地或通過從屬操作完成操作的過程。它對執行的持續時間和執行與其調用者之間的控制關係進行建模。在傳統的計算機和語言上,激活對應棧幀的值。
見call,sequence diagram。
語義
激活是執行某個操作的實例,它包括這個操作調用其他從屬操作的過程(見Call)。其內容包括一個只能訪問激活的局部變量的集合、一個方法內的當前位置(或其他行爲描述)和一個表示調用內容的激活的引用(噹噹前激活終止時,它將恢復控制)。沒有返回引用的激活必定是在一個主動類對象的狀態機上的轉換的結果,當轉換完成時,狀態機簡單地等待下一個事件。
請注意這個定義將一個普通過程描述成可以在一個典型的馮·諾依曼機上實現。但是它以一種普通的方式表示即它也適用於分佈環境,該環境中沒有共享內存並且在不同的內存空間中堆棧包含一張被鏈接的激活表。
表示法
激活在順序圖中用一個細長的矩形框表示,它的頂端與激活時間對齊而底端與完成時間對齊。被執行的操作根椐不同風格表示成一個附在激活符號旁或在左邊空白處的文字標號。進入消息的符號也可表示操作。在這種情況下,激活上的標號可以被忽略。如果控制流是過程性的,那麼激活符號的頂部位於用來激發活動的進入消息箭頭的頭部,而符號的底部位於返回消息箭頭的尾部。
如果有多個對象的併發活動,那麼每個激活表示一個併發對象的執行。如果對象之間不進行通信,那麼併發激活是獨立的且它們的相對執行次數是不相關的。
在過程代碼中,激活表示一段持續時間,在這段時間中過程或者被初始過程調用的從屬過程是活動的。換而言之,所有活動的嵌套過程激活被同時表示。這些同時發生的嵌套激活是傳統計算機的計算棧幀。對於激活的對象的第二次調用而之,第二次激活的符號第一次激活符號的右邊,這樣它們好像疊加了起來。被疊加的調用可以嵌套於任意的深度。調用可以針對同一個操作(即遞歸調用),也可以針對用一個對象的不同操作。
示例
圖13-7表示由調用引起的激活,包括遞歸調用。
13-7.gif
圖13-7激活
11. active(活動的/主動的)
活動狀態是已經被進入且沒有退出的狀態,由一個對象保持。
見active class, active object。
語義
當進入一個狀態的轉換被激發後,這個狀態變多活動的;當離開這個狀態的轉換激發時,這個活動的狀態不再活動。如果一個對象有一個控制線程,那麼至少有一個狀態是活動的(在退化的例子中,類只有唯一的狀態,在這種情況下,一個事件的反應總是相同的)。如果一個狀態在一個對象的類的狀態機中是活動的,那麼這個對象被認爲是擁有這個狀態。
一個對象可以同時擁有多個狀態,活動狀態的集合叫做活動狀態配置。如果一個嵌套的狀態是活動的,那麼包含它的所有狀態都是活動的。如果對象允許併發性,那麼多個併發的子狀態可以是活動的。每個轉換至多影響活動狀態配置中的數個狀態。轉換中沒有被影響的活動狀態仍然是活動的。
一個組成狀態可以是順序的或是併發的。如果這個狀態是順序的和活動的,那麼它的後繼子狀態的一個是活動的。如果這個狀態是併發的和活動的,那麼它的後繼子狀態的每一個都是活動的。即,一個組成狀態擴展成一個活動子狀態的與或樹,在它的每一層,特定的狀態是活動的。
構造跨越組成狀態邊界的轉換時必須保持這些併發性約束。一個順序組成狀態中的轉換通常有一個源狀態和一個目標狀態。激發這樣一個轉換並不改變活動狀態的數量。對併發組成狀態的每個子區域,併發組成狀態的轉換通常有一個源狀態和一個目標狀態。這樣一種轉換叫做分叉。如果一個或多個作爲目的地的區域被忽略,那麼每個被忽略的區域的初始狀態被隱含當作目的地;如果其中的一個區域缺少初始狀態,那麼模型是病態的。激發這種轉換增加了活動狀態的數量。從併發組成狀態退出時,則剛好相反。
見state machine,其中包含有關併發狀態和複雜轉換語義的詳細討論。
示例
圖13-8的上部爲一個狀態機的例子,它既有順序的又有併發的組成狀態。轉換被忽略。圖的底部表示可以併發活動的狀態的不同的配置。在這個例子中,有四種可能的活動狀態的配置。只有葉狀態是具體的,而更高層次的狀態是抽象的,即一個對象可以不屬於這些狀態也可以不屬於它們的嵌套葉狀態。舉個例子,不屬於Q的子狀態的對象可不屬於狀態Q。因爲Q是併發的,所以如果Q是活動的,C和D也必須是活動的。每個葉狀態對應一個控制線程。在更大的例子中,可能的配置數量成指數增長,而且不可能將它們全部表示出來。
圖13-8併發活動狀態。
13-8.gif
圖13-8 併發活動狀態
12. active class(主動類)
主動類的實例是主動對象。
見active object。
語義
主動類的實例是主動對象,主動類的構造型是進程和線程。
表示法
主動類用深色邊線的框。
舉例
圖13-9表示一個主動類和其被動類的類圖。圖13-10表示含有對應於這個模型的主動對象的協作圖。
13-9.gif
圖13-9 主動類和被動類
13-10.gif
圖13-10主動對象和併發控制間的合作
13. active object(主動對象)
主動對象擁有一個控制線程並且能初始化控制活動,它是一個主動類的實例。
見passive object,process,thread。
語義
一個主動對象不在另一個線程、棧幀或狀態機內運行。在整個系統的執行中,它具有獨立的控制期。從某種定義來說,它是一個線程。每個主動對象是不同的執行集中點;主動對象不是再進入的,並且如果沒有附加對象的創建遞歸執行是不可能的。
主動對象是傳統計算機術語中執行棧幀的基礎。一個主動對象的創建初始化了一個新的狀態機實例。當狀態機執行轉換時,一個執行棧幀被建立並且一直存在直到轉換動作完成,且對象等待外部引入。因此,一個主動對象不在另一個對象的作用域內運行。它能被另一個對象的動作創建,但是一旦被創建,它就獨立存在。創造者可以是一個主動的或被動的對象。主動對象用事件驅動。別的對象對它的操作應該作爲調用事件由主動對象實現。
被動對象可以作爲動作的一部分由另一個對象創建。它有自己的地址空間。被動對象沒有控制線程。它的操作在一個主動對象的棧幀內被調用。然而,它可以有一個狀態機來建模,來表示由於對它的操作引起的狀態的改變。
一個傳統的操作系統進程最好等同於一個主動對象。操作系統線程可以由或不由主動對象實現。
主動-被動的區分基本上是一個設計決定而且不限制對象的語義。主動的或被動的對象都可以有狀態機,它們還能交換事件。
表示法
主動對象的協作角色在協作圖中用具有重邊線的矩形表示。通常,主動對象角色表示成與其內在部分的組合。
主動對象也可以用具有重邊線的對象符號表示,名字下有下劃線,但是主動對象僅在執行例子中出現,因此不那麼普通了。
特性關鍵字{active}也可以用來表示主動對象。
示例
圖13-10表示一個工廠自動化系統的三個主動對象:一個機器人、一個爐子和一個工廠管理者,其中管理者是一個控制對象。三個對象都同時存在和執行。工廠管理者在步驟1初始化一個控制線程,這個線程會分成兩個分別由爐子和機器人執行的併發控制線程(A1和B1)。當每一個執行完畢,就合併到工廠管理者的步驟2。每個對象仍然存在且保持狀態直到下一個事件到來。
14. active state configuration(活動狀態配置)
活動狀態配置是在狀態機內同時活動的一個狀態集合。一個轉換的激發可以改變這個集合中的一些狀態,而另一些不變。
見active,completion transition,state。
15. activity(活動)
活動是狀態機內正在進行的非原子執行。對比:動作。
見completion transition,state。
語義
活動是狀態機內子結構的執行,子結構允許中斷點的存在。如果一個轉換強迫從控制域退出,那麼該轉換放棄這個活動。活動並不由內部轉換的激發終止,因爲並沒有狀態的改變。內部轉換的動作會明確地終止它。
活動可以由嵌套狀態、子機引用或活動表達式建模。
示例
圖13-11爲一個警報系統,它說明了動作和活動的區別。當事件detect intrusion發生時,系統激發一個轉換。作爲轉換的一部分,動作call police發生。它是一個動作,所以通常是原子的。當動作被執行時,沒有事件會被接受。當動作被執行後,系統進入Sounding狀態。當系統處於這個狀態時,它執行sound alarm 活動。活動需要時間來完成,中斷活動的事件可能會在此時出現。在這種情況下,sound alarm活動自己並不會中斷,只要系統處於sounding狀態它就會持續下去。當reset事件發生時,轉換被激發並將系統返回到monitoring狀態。當sounding狀態不再是活動的,它的活動sound alarm也被終止了。
13-11.gif
圖13-11 動作和活動
16. activity diagram(活動圖)
activity graph。
17. activity expression(活動表達式)
活動表達式是對非原子計算、活動的文字表達式。這種表達式理論上講可分爲原子部分,但是允許對整個事情進行文字表示會更方便一些。活動表達式的執行可以被使控制狀態的無效轉換終止。
語義
活動表達式是由某些語言(如編程語言或其他正式語言)表示的有用的過程或算法。它也可以用人類語言來表示。在這種情況下,工具不能執行它,它也不能被檢查錯誤和其他屬性。但是在工作的初期階段,這已足夠了。它也可以表示連續的真實世界操作。
表示法
活動表達式用由某種語言(下例爲英語)解釋的文字表示。
示例
do/invertMatrix 有限但費時
do/computeBestMove(time-limit) 計算直到時間用盡
do/sound siren 連續運行直到結束
18. activity graph(活動圖)
活動圖是狀態機的一個特殊例子,在該狀態機中所有的或大部分的狀態都是活動狀態或動作狀態,所有或大部分的轉換由源狀態中活動的完成所觸發。活動圖表示一個程序或工作流。活動圖是模型中的完整單元。
見state machine
語義
活動圖是強調計算過程中順序的和併發步驟的狀態機。工作流是被活動圖所建模的過程的例子。活動圖通常出現在設計的前期,即在所有實現決定前出現,特別是在對象被指定執行所有活動前。這種圖是狀態機的特例,在它當中狀態代表活動的執行,就像一個計算或真實世界不間斷的操作,而轉換由操作的完成觸發。活動圖可以附屬於操作和用例的實現。
在活動圖中狀態主要是活動狀態或動作狀態。活動狀態是某種狀態的速記,該狀態有內部計算和至少一個輸出完成轉換,該完成轉換由狀態內活動的完成來激發。如果轉換有監護條件,那麼可以有多個輸出轉換。活動狀態不應該有內部轉換或基於明確事件的輸出轉換。對於這種條件要用標準狀態。動作狀態是原子狀態,即它們不會被轉換中斷。
通常,活動狀態用於對這一個過程的某個執行步驟建模。如果模型中的所有狀態都是活動狀態,那麼計算的結果不會依賴於外部事件。如果併發活動不訪問同一個對象且併發活動的相對完成時間不影響結果,那麼計算過程是確定的。
活動圖可以包含普通的等待狀態,該狀態的退出由事件觸發。但是這種使用降低了集中於活動的目的。如果有多個普通狀態,則用普通狀態模型。
* 動態併發性。具有動態併發性的活動狀態表示併發執行多個獨立的計算。活動與一個參量表集合同時調用。集合中的每一個成員都是活動的並行調用的參量表。調用是互相獨立的,當所有的調用完成時,活動結束並觸發它的完成轉換。
* 對象流。有時,查看一下操作和作爲它的參量值或結果的對象之間的關係是有好處的。一個操作的輸入和輸出可以表示成一個對象流狀態。它是一個狀態的構造型,表示在計算過程中特定點的給定對象的存在。爲了更精確,輸入或輸出對象可以在它的類中聲明處在指定的狀態。例如,"簽署合同"操作的輸出爲"已簽署"狀態的合同類的對象流狀態。該對象流狀態可以是其他多個操作的輸入。
* 泳道。活動圖中的活動可以依照不同的準則劃分爲幾組。每個組代表活動職責的一些有意義的部分,例如,商業組織負責給定工作流的某一步。根據它們的圖形表示法特徵,每個組被稱作泳道。
表示法
活動圖是狀態機中的一種,但是幾種速記表示法也適用於活動圖,如:活動狀態、分支、合併、泳道、對象流狀態、狀態類、信號發送和信號接收表示法和延遲事件。
請看一些可選符號的控制圖標,它們可用於活動圖表示法和。
舉例
圖13-12表示一個活動的工作流,它用於處理劇院售票處的訂單。它包括一個分支和隨後的合併,取決於訂單是預訂的還是個人票。分叉初始化邏輯上同時發生的併發活動。它們的實際執行可以重疊也可以不重疊。併發性由隨後一個相對應的結合終止。如果只涉及到一個人,那麼併發活動可以以任何次序執行(假定它們不能被同時執行,這是模型所允許的,但在實際中非常困難)。例如,售票處的人員可以先分配座位,再授予贈品,再借記賬戶;或者他們可以先授予贈品,再分配座位,再借記賬戶,但是他們只有在分配座位後才能借記賬戶。
13-12.gif
圖13-12 活動圖
分叉的一個輸出部分有一個監護條件,檢查預訂者是不是會員。這是一個條件線程,它只有在監護條件被滿足時纔會激發。如果這個線程沒有被激發,那麼隨後相對應的結合的輸入部分被認爲已完成。如果預訂者不是會員,則只有一個線程被激發,它負責配座位和借記賬戶,但是不會等待結合處的同步。
* 泳道。活動圖中的活動可以分成爲幾個區域,每個區域在圖中用虛線分開因此被叫做泳道。泳道是活動圖的內容的組織單元。它沒有內在的語義,但可以根據建模者的意願使用。通常,每個泳道代表真實世界組織內的一個組織單元。
示例
圖13-13中,活動被泳道分成三個部分,每個部分對應一個不同的資金保管者。雖然在這個例子中每部分都對應於對象,但是UML並不要求這麼做,會有明顯的類對應於每個部分,而且這些類可能是執行操作以實現已完成模型的每個活動。
13-13.gif
圖13-13
這張圖也表示了對象流符號的使用。對象流對應於一個訂單對象經過整個活動的不同狀態。例如,符號Order[placed]表示在計算中的位置,一個訂單已經被提高到Request Service活動的placed狀態,但是還沒有被Take order活動使用。當Take order活動完成後,訂單進入entered狀態,對象流符號將該狀態表示在Take order活動的輸出上。該例中的所有對象流表示處於聲明中不同時刻的同一對象。因爲它們表示同一對象,故它們不能同時存在。如圖所示,一條連續的控制路徑可以從它們中畫過。
* 對象流。由動作輸入或輸出的對象可以表示爲對象符號。符號表示處於計算中某一點的對象,在該點對象適合作爲輸入或作爲輸出。虛線從活動狀態活動輸出之一。虛線箭頭也可以表示從對象流到對象作爲輸入的活動狀態的輸入轉換。通常,同一個對象可以作爲一個活動的輸出和一個或多個後繼活動的輸入。
當對象流箭頭(虛線)滿足冗餘約束時,控制流箭頭(實線)可以被忽略。換而言之,當動作產生的輸出是後繼動作的輸入時,對象流關係包含一個控制約束。
* 狀態類。通常,同一個對象被一些改變它的狀態的後繼活動所控制。爲了更加準確,對象可以在圖中出現多次,每次出現表示它生命中的不同的狀態。爲了區分同一個對象的多次出現,每個點的對象的狀態可以放在方括弧內並附加在類的名字旁,例如PurchaseOrder[approved]。這個符號也可用於協作圖。
見可用於活動圖的其他符號的控制圖標。
* 延遲事件。有時,當其他活動進行時,有一種事件必須爲了晚一些使用而延遲(通常,沒有立即處理的事件會被遺失)。延遲事件是放置在內部隊列中,直到它被使用或被拋棄的事件。如果在狀態或活動中發生延遲事件,該狀態或活動將對它們進行說明,其他事件必須被立即處理,否則將被遺失當狀態機進入一個新狀態時,如果新狀態不延遲這些事件,那麼所有的延遲事件會發生。如果新狀態中的轉換由先前狀態中的延遲事件觸發,那麼轉換立即激發。如果幾個轉換隱含地能發生,則它們中的哪一個會激發並不明確,且施行一條規則以選擇一個要激發的轉換是語義變更點。
如果一個事件在它所延遲的狀態中發生,它可能觸發一個轉換,在這種情況下它不放在隊列中。如果這個事件不觸發轉換,則它被放在隊列中。如果活動狀態改變,那麼隊列中的事件可以觸發新狀態中的轉換,但是如果它們在新狀態中仍然是延遲的,那麼它們仍然在隊列中。如果一個事件在組成狀態中必須是延遲的,但可以促使一個或多個子狀態中的轉換,那麼使事件不再延遲以觸發轉換的能力是很有用的。否則,事件將不得不在每個子狀態中延遲而不觸發轉換。請注意如果一個延遲事件與轉換的觸發器事件相一致,但是不滿足監護條件,那麼這個事件並不觸發轉換,也不會從隊列中移去。
一個可延遲事件在狀態內表示,後面有一個反斜槓和特殊操作defer。如果事件發生且沒有觸發轉換,則它被保存起來,且當對象轉換到另一個狀態時再次發生。當對象到達一個它不會被延遲的狀態時,它必須被接受或被忽略。若沒有defer聲明則可以取消先前的延遲。defer指示符可以放於一個組成狀態上,這樣事件就在整個組成狀態內延遲。
動作狀態是原子的,所以當這些狀態活動時隱含地延遲任何此時發生的事件,無需將它們標記爲延遲的。發生的事件被延遲直到動作完成,這時事件可以觸發轉換。
13-14.gif
圖13-14 延遲事件和控制圖標
舉例
圖13-14表示者咖啡的步驟。在這個例子中,外部對象(coffeepot)沒有表示出來,表示出來的僅僅是由人直接執行的活動。打開壺的動作被建模成發送到壺的事件。活動Get Cups發生在打開咖啡壺之後。在得到杯子後,需要等待直到燈熄滅。然而,存在一個問題,如果light goes out 事件在Get Cups活動完成之前發生,那麼因爲狀態機沒有準備好處理事件,它將會丟失。爲了避開丟失事件的危險,活動狀態Get Cups被標識爲延遲light goes out事件。如果事件在活動還在執行時發生,事件不再會丟失。相反地,它被保存在隊列中直到狀態機離開Get Cups狀態,這時它被執行且觸發了轉換。
請注意light goes out 事件不是Get Cups狀態的觸發,因此當它出現時也不會終止活動的進行。這個事件是Get Cups活動完成後的一個接收狀態的觸發者。
* 動態併發性。有一個不確定值的動態併發性用活動符號右上角的複合串表示(如圖13-15)。這預示着活動的多個拷貝同時出現。動態活動接收參量表的集合,細節必須用文字描述。如果併發性應用於多個活動,則它們必須包含於一個組成活動中,這個組成活動得到多重指示。
13-15.gif
圖13-15 動態併發性
* 圖結構。狀態機必須被良好地嵌套,即它被分解成併發的或順序的子狀態。對一個活動圖,分支和分叉必須被很好地嵌套。每個分支必須有一個對應的合併,每個分叉必須有一個相對應的結合。這對活動圖來說有時不方便。通常情況是採用部分有序圖,其中沒有直接的循環,但是分叉和合並不必相匹配。這種圖不是良好嵌套的,但是它可以經過指定活動到線程和通過當轉換跨越邊界時引入同步狀態兩種方法來轉變爲良好嵌套圖。分解不一定是唯一的,但是對部分有序圖來說所有的分解將產生相同的可執行語義。所以,對一個簡單的部分有序圖沒有必要表示一個明確的分解或同步狀態。對涉及到條件和併發性的更復雜的圖,可能需要更明確的分解。
19. activity state(活動狀態)
活動狀態表示一個具有子結構的純粹計算的執行,通常爲操作或位於其內的聲明的調用或真實世界程序的執行。活動狀態可以被使轉換離開狀態的事件從外部中斷。活動狀態不必自己中斷。對於它可以活動多長時間是沒有限制的。
見activity,completion transition。
語義
活動狀態是具有內部計算和至少一個輸出完成轉換的狀態,當狀態中的活動完成時該轉換激發(如果有監護條件則可以有幾個這種轉換)。活動狀態不應該有內部轉換或基於確切事件的輸出轉換。對於這種情況要求使用普通狀態。活動狀態通常用於對算法執行中的一步建模。如果模型中的所有狀態都是活動狀態且併發的活動不訪問同樣的值,那麼計算是確定的,即使它涉及併發執行。
活動狀態可以引用一個子機,通常爲另一個活動圖。這與將活動狀態擴展成一個子機網絡的搭貝是等價的。它是狀態機的子例程。
活動狀態是一個程序的執行過程的狀態而不是一個普通對象的狀態。
動作狀態是原子的活動狀態,即當它是活動時不會被轉換所中斷。它可以被建模成只有一個入口動作的活動狀態。
活動狀態可以被用於普通的狀態機,但是它們更常用於活動圖。
離開一個活動狀態的轉換通常不包括事件觸發器。輸出轉換被狀態中活動的完成隱含地觸發。轉換可以包括監護條件和動作,注意所有有關違反活動的轉換的可能條件都要涉及到,否則控制被掛起。如果多個監護條件賦值爲真,那麼選擇不確定的。
對於其他條件使用普通狀態。
表示法
活動狀態用以下形狀表示:上下邊是直線,左右邊是凸弧(如圖13-16)。活動表達式被放在符號內。在圖中活動表達式不必是唯一的。
13-16.gif
圖13-16 活動
討論
動作狀態用於簡短的簿記操作而活動狀態用於任何有持續時間或複雜性的計算。這意味着動作可以鎖定系統所以它必須是短暫的,但是活動可以被中斷,所以如果一些緊急的事情發生不要求系統去完成它。UML語義並不阻止長動作,但是代碼生成器可以合理地假定動作打算立即完成,同時活動對於其他動作是可中斷的。
20. activity view(活動視圖)
活動視圖是系統的一個方面,它將行爲的說明作爲由控制流連接的活動進行處理。活動視圖包含活動圖並且表示在活動圖上。它鬆散地與其他行爲視圖組織在一起。
見activity graph
21. (參與者)
參與者是直接與系統相互作用的系統、子系統或類的外部實體的抽象概念。參與者參與到用例或一組連貫的用例中以完成整個目標。
見use case。
語義
參與者刻劃和抽象了一個外部用戶或與系統和類元相互作用的一個相關的用戶集合的特徵。參與者是具有集中的目的和含義的理想化形式,不一定有確切對應的物理對象。一個物理對象可以兼有多個無關聯的目的,所以可以由多個參與者建模。不同的物理對象可以包含同樣的目的,故在這個方面可以由同一個參與者建模。用戶對象可以是一個人、一個計算機系統、另一個子系統或另外一種對象。例如,一個計算網絡系統的參與者可以包括Operator、System Administrator、Database Administrator和普通的User,也可以有非人類參與者,如RemoteClient、MasterSequencer和NetworkPrinter。
每個參與者定義了一個角色集合,當系統的用戶與系統相互作用時會採用它們。參與者的一個集合完整描述了外部用戶與系統通信的所有途徑。當一個系統被實現,參與者也被物理對象實現。一個物理對象如果可以滿足多個參與者的角色,那麼它就可以實現多個參與者。例如,一個人可以既是一個商店的售貨員又是顧客。這些參與者不是本質上相關的,但是它們可以由一個人來實現。當一個系統的設計被施行時,系統內的多個參與者被設計類實現(見realization)。
參與者與系統的不同的交互作用量化爲用例,用例是設計系統和它的參與者的連貫的功能塊,用來完成對參與者有意義的事情。一個用例可以包括一個或多個參與者,一個參與者到以參與一個或多個用例。最終,參與者由用例和參與者在不同用例中所擔任的角色決定。沒有參加任何用例的參與者是無意義的。
用例模型刻劃了一個實體(如系統、子系統或類)與外部實體相互作用時產生的行爲的特徵。外部實體是實體的參與者。對於一個系統,參與者可以既由人類用戶又由其他系統實現。對於一個子系統或類,外部元素可以是整個系統的參與者,或者參與者可以是系統內的其他元素,如其他子系統或類。
參與者實例通過與用例實例傳遞消息實例(信號與調用)來與系統通信,在實現層,與實現這個用例的對象傳遞消息實例。這通過參與者和用例之間的關聯來表達。
參與者可以列出它發送和接收的信號集合。參與者也可以有一組它所支持和需要的接口。參與者的接口必須與和它通信的每個用例的接口相容。換而言之,參與者必須接受用例發送的所有信號,而且它不能發送給用例不能接收的信號。參與者的接口限制了參與者如何映射到類上。參與者也可以有一組表示它的狀態的屬性。
泛化
多個參與者可以有相同點,即它們可以以同樣的方式與同一組用例交流。這個相同性用與另一個參與者的泛化關係來表示,它對參與者的共同方面進行建模。後代參與者繼承了由祖先參與者擁有的角色和與用例的關係。一個後代參與者的實例常常在祖先希望被用到時使用(替代原理)。一個後代包括它的祖先的屬性和操作。
表示法
參與者可以用具有構造型實體《actor》的類符號(矩形)表示。標準的參與者構造型圖標是一個小人,參與者的名字在圖的下面。參與者可以用間隔來表示它接收到的屬性和事件,它也可以用依賴關係表示它發送的事件。這些是普通類元的能力(如圖13-17)。
13-17.gif
圖13-17 參與者符號
22. actual parameter(實際參數)
見argument。
23. aggregate(聚集)
聚集聚全合關聯(整體與部分)中整體的類。
24. aggregation(聚集)
聚合是一種關聯形式,它指明一個聚集(整體)和組成部分之間的整體與部分的關係。
見composition。
語義
一個二元關聯可以聲明爲是一個聚合-一種整體與部分的關係。關聯的一端指出聚集而另一端是無記號的。兩端不能同時是聚集(或組成),但是兩端可以同時是無記號的,這時它不是聚合。
從聚合關聯實例化形成的鏈遵循若干規則。聚合關係是可轉換的,非對稱地跨越所有聚合鏈接,甚至跨越那些來自不同聚合關聯的鏈接。可轉換意味着如果從B到A有聚合鏈接的路徑,那麼說"B是A的一部分"是有意義的。非對稱性意味着在聚合鏈接的路徑中不存在循環。即一個對象不能直接地或間接地作爲它自己的一部分。將兩條規則合在一起,從所有聚合關聯得到的聚合鏈接組成的圖形就形成了一個部分有序圖,該圖沒有循環(樹是一個具體而又常見的部分有序的情況)。圖13-18給出了一個例子。
13-18.gif
圖13-18 對象的聚集是無循環的
從對象B到對象A的鏈接的有向路徑表示存在從類B到類A的合集關聯的有向路徑,但是關聯的路徑會涉及到循環,在這當中同一個類可以出現多次。一個類到它自己的聚合關聯的有向路徑是一個遞歸。
有一種更強的聚合形式叫做組合。組成是有着附加約束的聚集,這些約束是,一個對象只能是一個組成的一部分且組成對象有安置它的每一部分的責任,即對它們的創建和銷燬負責。
見composition。
在普通的聚集中,一個部分可以屬於多個聚集,而且它可以獨立於聚集存在。通常,聚集"需要"部分,即它可被認爲是部分的積聚。但是部分可以獨立存在,而不必認爲僅僅是"部分"。例如,路徑可以認爲是段的集合。但是段可以獨立存在而不管它是不是路徑的一部分,並且同一段可以出現在不同路徑中。
見accociation及accociation end以瞭解聚合的更多特性。
表示法
聚合用一端用連接到聚集類的表示的關聯線表示(如圖13-19)。如果該聚合是一個組,那麼菱形是實心的,見後文圖13-68。關聯的兩端不能同時有聚合標識。
聚合類可以有多個部分。聚集類和每個部類之間的關係是分離關聯(圖13-20)。
如果有兩個或多個聚合關聯指向同一個聚集類,那麼可以通過將聚合端結合成一個獨立的部分來將其畫成一棵樹(如圖13-21)。這要求聚合端的所有屬性都是一致的,如,它們必須有相同的多重性。將聚合畫成一棵樹純粹是表示方達的選擇,並沒有附加的語義。
13-19.gif
圖13-19 聚集表示法
13-20.gif
圖13-20帶有多個部分的聚集。
13-21.gif
圖13-21 同一個類的多重聚合的表示形式
討論
聚合和關聯之間的區別通常是個人喜好的問題而不是語義的區別,聚合聚合關聯。聚合表示了這樣一種思想:聚集是它的每一部分的總和。實際上,它加入到關聯的實際語義是聚集鏈不能組成循環這一約束。其他約束,如存在依賴性,由多重性而不是聚集標識說明。除了附在聚合上的很少的一部分語義外,其必要性得到了大家的認同(因爲各種不同的原因)。可把它作爲建模的一帖安慰劑。
幾種次要的特性與聚合有關,但是它們不夠可靠故不能使它們成爲聚合定義的一部分。這些特性包括從聚集到部分的操作的傳播(如移動操作)和緊縮內存分配(以便聚集和它的遞歸部分能夠在一次內存交換中高效加載)。一些作者對幾種聚合,但是區別相當細微且可能對通用的建模是多餘的。
聚合超越特殊關聯的特性。可以跨越不同的類組成聚合。聚合對所有沒有循環聚合鏈包括來自不同關聯的鏈。聚合關聯(包括組合關聯)的實例實施了一條約束,在某種意義上,聚合是關聯的一種泛化,在聚合中,約束和一些操作應用於許多特定種類的關聯。
組合有更多具體的語義,它們對應於物理包含和所有權的不同觀點。當每個部分由一個對象所擁有並且每個部分沒有獨立於其擁有者的生命期,那麼這時用組比較合適。特別是在當擁有者被創造時,所有的部分也必須分配和初始化;當擁有者毀滅時每個部分也不會存活。類的屬性有這些特性,雖然它們沒有被明確地建模成一種組合,但是仍然可以被認爲如此。通過使用組合,可以避免存儲器管理的負擔、沒有指向任何對象的指針的危險以及被遺棄的對象的危險。組合也適用於這樣的情況,由於壓縮和操作的原因,一組屬性已經被分離到一個不同的類中,但是這些屬性真正適用於主類。雖然用來實現關聯的包容器類也通常是組成部分的候選者,但是它們必須由代碼生成器生成且不會顯式地被建模。請注意一個組成部分,如包容器類,可以包含對非組成部分的引用或指針,但是被引用的對象不會在引用對象毀滅時也被銷燬。

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