第二部分:XDE中的模式機制
1 概述
在前一期的系列文章中,我們對模式,特別是設計模式在UML中的建模方法作了簡要地,理論上的介紹。現在該要進行實踐了。現在支持模式建模並能夠基於模式進行應用程序開發的工具並不是很多。Rational XDE是其中最為著名的一個,並且確實提供了極為優秀的功能。
XDE的Java版有兩種,一種是基於Eclipse內核的獨立運行版本(目前只支持Eclipse1.0)。另為一個是集成在WASD中的,作為WASD的一個插件同其以其運行(目前只支持WASD 4.0)。實際上WASD使用的就是Eclipse的內核,所以,這兩者在功能上(甚至外觀上)都沒有多大的區別。現在Rational已經被IBM所合並,所以有足夠的理由可以相信,在未來的WSAD中,XDE的功能會被更加完美的整合到其中。
XDE最大的賣點有兩個,一個是分析設計同代碼編寫在是在同一個IDE中完成的,並可以進行正向-逆向工程,完美的實現迭代開發中所需要的模型-代碼的映射。另外一個就是這篇文章的主題:模式的定義和應用。你不僅可以使用XDE中預定義好了的23個經典的GoF設計模式,還可以自己定義模式,在開發中應用它們,或者導出供其他人使用。
模式機制是XDE中實現重用的核心技術。你可以通過這個機制來實現模型元素和其它制品的重用。它提供了Model-to-Model和Model-to-Code的變換功能。這使得你能夠將一個涉及的模型作為來幫助一個特定的設計。它還是得你能夠將一個模式中的元素內容合並到已存的設計模型中。
2 XDE中的模式描述
在XDE中,模式的描述基本上遵循了UML所定義的參數化協作標准。但是,由於UML中定義的只是如何來對模式建模,而對如何定義模式,應用模式,以及具體的代碼生成並沒有過多涉及。因而,XDE在UML的基礎上,作了一些合理的擴展。
首先,我們來看一看Asset的概念。一個Asset是一些軟件制品的集合,它們被組織在一起以期能夠解決某一個問題。Asset能夠通過其定義的可變點(Variability Point)來進行擴展,在進行Asset重用的時候,開發者需要對這些可變點提供具體的內容來充實Asset,以完成Asset的重用。
Rational現在推崇一種Asset Based Development過程方法,來作為其對RUP的一個補充,Asset就是其關鍵。這兒並不打算對Asset和Asset Based Development作過多地論述,那已經偏離了這篇文章的主題。從模式這個范疇而言,你可以簡單的把Asset看作是模式的定義,描述及其具體的實現。
在XDE中, Asset表示為一個構造型為<<Asset>>的包。被申明為<<Asset>>的包可以被導出以利於在不同的開發者,甚至不同的工具中重用,只要它們都遵循Asset的規范Reusable Asset Specification。
模式是一種Asset,但是Asset並不一定是模式。一個模型可以被包裝在一個Asset中,而其中並不帶有任何的模式描述。XDE能夠處理這兩種可重用項目。在XDE中,模式表示為包含在一個<<Asset>>包中的,帶有模板參數的合作圖。有很多種方法可以創建一個<<Asset>>包,但需要注意的是,創建一個UML的包並手工地將其版型設置為<<Asset>>並不會將這個包注冊為模式。
在XDE中,<<Asset>>包可以被導出為一個.ras文件。一個.ras文件實際上就是一個zip文件,不過它有著自己的內容結構,這和J2EE中的.war文件很類似。它使用了rasset.xml和resource.xml這兩個xml文件來提供對這個壓縮文檔的描述。RASAsset.xsd文件是RAS的XML Schema,定義rasset.xml和resource.xml這兩個文檔的內容格式和含義。其它的文件是模型和文檔制品。
在XDE中,模式由如下的一些部分組成:
Asset
在一個模式的底部是一個版型為<<Asset>>的包。模式中涉及到的所有內容都包含在這個包中,它也是用來導出符合RAS規范的可重用模式的邏輯單元(實際的物理封裝單元可是一個包,也可以是一個模型)。模式也可以不存在於Asset包中,但是因為模式的創建目標,就是希望能夠通過RAS規范來進行重用的,所以並不推薦使用這種方法。
模板協作(Template Collaboration)
在模式Asset中就是template collaboration,它是模式的核心。幾乎模式所涉及的所有內容都定義在其中。模版參數的屬性可以通過Pattern Explorer來查看。
模板參數(Template Parameters)
一個模板協作包含有一個或者多個模板參數,每一個定義一個特定的模式輸入。例如,如果你想有一個名為MyClassInput的參數,你可以使用那個名字創建一個模板參數。
類型元素(Type Element)
每一個模板參數都有一個類型,通過其Type屬性來定義。例如,如果模板參數的類型是class,那麼這個模板參數就只接受類作為其參數值。這同在定義一個函數的參數時,需要指定其參數的類型(比如int)是一樣的。
基礎上下文(Root Context)
一個模式還有一個基礎上下文,在創建模式時所引入的其它元素被組織在這個地方。這些元素通常都會被直接創建,需要很少或者根本不需要參數來創建它們。比如在一個模式中會被用到的一個支撐類。缺省情況下,基礎上下文就是Asset包。你可以在Pattern Explorer中將其切換到其它的包中。
實際上在模式所在的Asset包中,可以存在任何類型的元素,比如描述模式結構的類圖,描述模式中參與者之間的交互的順序圖,等等,都可以被放在基礎上下文中,在模式被擴展的時候一起被復制到擴展點處。
為了提供對模型的可視化開發和表示,XDE在Eclipse的基礎上,添加了新的Model透視圖(Perspective)。實際上所有模型相關的內容,不僅僅是模式,都是在這個透視圖中實現的。而對模式,除了所有模型公用的Model Explorer外,還有一個Pattern Explorer和Pattern Property視圖來提供對模式的定義和描述。對這些界面的使用都還比較簡單,關鍵的是要搞清楚那些屬性,設置值是來做什麼的。除了上面的那些標准的Eclipse圖形元素外,XDE中還引入了Pattern Wizard來幫助你完成模式的應用。
3. 模式的應用
XDE模式的應用,可以看作是一種基於模版(Template)的方法:定義好的模版參數,通過創建,或者同已有模型中同模版參數類型一致的元素的融合,來完成對模式的擴展。模式中沒有被定義為模版參數的元素,將在擴展點處被自動創建。
在應用一個模式的時候,有兩個基本概念:
1、擴展點(expansion location):這是在模式被應用後,生成的類和其它元素被放置的地方。即使是模式並沒有生成任何的元素,而且其基本上下文中也沒有涉及到任何得元素,對於模式的應用而言,這個擴展點仍然是需要的。
2、綁定(binding)和綁定點(binding location)。綁定是模式中的參數被賦予具體的參數值的過程,這個參數值可以是用戶指定的一個模型元素,也可以是用缺省值自動創建的元素。當一個模式被應用之後,在指定的綁定點中就有一個綁定對象被創建,它被用來維護這個模式的模版參數和具體的參數值之間的綁定關系。通常綁定的作用是用來在修改了模式之後,重新應用模式,而不需要在通過Pattern Wizard來再次設定應用模式所需的參數值,你也可以直接在綁定對象中修改被綁定的參數值。在缺省的情況下,綁定點和擴展點是同一位置。
有了這兩個基本的概念後,我們可以把模式的應用簡單的描述為如下的過程:在擴展點所在處,通過對模式中所定義的參數指定具體的參數值,並將這些參數值實例化到具體的模型中。而模式所在包中其它的除了模版參數外的其它元素也會被相應的創建,包括類圖,順序圖等。
我們還是以Command模式為例,來例示一個模式的定義和應用。
要應用模式,我們在需要應用的模型上調出快捷菜單,選擇Apply Favorite Pattern,然後再選(GOF)Command模式,如下圖:
然後出現Pattern Wizard,幫助你來輸入模式的參數值:
Pattern Wizard的第一個頁面上給出了詳細的模式說明,以及主要的參與者之間的交互,以幫助開發者選擇合適的模式。點下一步之後,就是要輸入參數值了:
一般的參數值的指定有兩種方法:
Selected Element:如上圖,需要在模型中指定一個類型相符的元素,這兒是一個類。這種方法將在已有的元素中融合入模版參數中定義的內容,而不對原有的元素造成任何的影響。
Generated Value:如下圖,需要為給定的參數提供一個字符串名字,並生成一個全新的相應名字的元素。
當為每一個參數均指定了一個綁定值後,再分別指定擴展點和綁定點即可:
這樣,一個模式的應用就完成了。Command模式中所描述的語義信息,以及具體的模型元素都被引入到現有的模型中。
實際上,在XDE中應用模式的方法有很多,但是使用Pattern Wizard是標准的也是最為簡單的方法,而且XDE也允許在定義一個模式的時候,為Pattern Wizard中的每一個頁面都做詳細的定制,使得模式的應用更為方便簡潔。其它的方法,比如使用構造型,使用綁定對象等方法,這兒不再詳述。
上面對在XDE中模式的應用過程作了一個簡要地描述。而從XDE的內部工作機制來看,模式的應用是分為如下的三步來進行的:
1. 綁定:為模式中的每個模版參數指定具體的參數值。
2. 參數的計算/映射:計算參數相關的內容,比如約束,腳本等等。並根據所指定參數值的數目,進行參數值的映射和匹配。
3. 展開:當所有的參數都確定之後,模式就能夠被展開了。傳遞進去的參數值會被修改或創建,然後復制到擴展點處,模式的展開完成。
對這個過程的理解是很重要的,因為我們不僅僅需要應用已有的模式,還需要來定義,創建模式。對這個過程的理解,能夠讓我們對模版參數以及其綁定之間的關系有了更清楚地認識。而這恰恰就是模式定義的核心。
4. 模式的定義
從上面的模式應用的例子可以很容易的看出,在XDE中,模式定義的關鍵在於對模版參數的定義,這包括有模版參數的類型,生成方式,等等。
在XDE中開發模式之前,還應該對抽象出來的模式進行細化,以使之能夠有具體的實現。比如,對於不同的語言,模式的實現也會有不同。細化的過程比較繁瑣,而且也沒有一個一定的准則,這兒就不多加討論了。我們詳細的關注,如何在XDE中開發一個模式。
在XDE中,一個模式的開發,可以遵循如下的步驟:
4.1 創建模式Asset
前面說過,一個模式被包含在一個構造型為<<Asset>>的包中,所以在創建一個模式之前,首先需要創建這個包。可以通過在Model Explorer的上下文菜單中選擇Add UML > Pattern Asset來創建這個包。如下圖所示,會出現如下的對話框:
上圖要注意的是一個Asset可以被定義在一個包中,以可以被單獨的定義在一個模型中。這將決定模式的基礎上下文是包還是整個模型。
4.2 為參與者定義模版參數
模式的參與者是模式中各個職責的承擔者,也就是模版參數所需要定義的地方。當然,模版參數還可以包含其他方面的信息,而不僅僅是模式的參與者。簡單的說,模版參數定義了所有模式需要被定制的方面。要創建一個模版參數,可以在Model Explorer中新創建的模式協作的上下文菜單中選擇Add UML > Template Parameter。再定義好模版參數後,還需要為其指定一個類型。在創建的模版參數的上下文菜單中選擇Add UML,然後選擇具體的類型:可以是類,方法,屬性,接口,字符串,整數等等。基本上大部分的UML元素都可以被創建為一個模版參數。當然,對一個模式的參與者而言,它的類型通常是類,或者接口。對被設置為類類型的模版參數,我們可能還需要向其添加屬性,方法等內容。對其中的方法,還可以為其指定代碼模版。這些內容都會隨著模版參數被引入到具體的模型開發中去。
我們還可以設置參數的生成方式。判斷模版參數值是需要選擇一個以存在的模型元素,還是新創建一個,或者從其它的模版參數中衍生出來?這幾種不同的生成方法取決於模版參數的Value Source值,它可以是上面的三種情況之一,或者是它們之間的組合。這在後面一節中的Value Source中有更細致的介紹。你可以在Pattern Explore中的Advanced Properties中設置Value Source的值。
4.3 創建模式的結構類圖
可以在模式的定義中包含一個或則多個類圖來定義模式的各個參與者之間的協作與關系。在Model Explorer中新創建的模式協作的上下文菜單中選擇Add Diagram > Class。
實際上,對於模式應用而言,這個類圖並不是必需的。但是,這個類圖能夠很好的對模式的結構作出描述,因而也是很必要的。
4.4 添加其它可選的模式元素
你還可以在Model Explore中為模式添加其它非模版參數的模型元素。這些元素被放置在模式的基礎上下文中,在模式被綁定展開的時候,他們也會被自動的創建,並放置在擴展點處。在Pattern Explorer中,你可以在模式的Root Context目錄下看到這些內容。
4.5 為模式參與者創建代碼模版
代碼模版為參與者中的方法填充具體的代碼實現。在某一個方法上調出其上下文菜單,選擇Code Templates > Bind,可以為這個方法創建一個新的代碼模版,或者選擇一個已有的代碼模版綁定到方法上。
在後面的一節中將有對代碼模版的專門描述。
這樣,一個完整的模式就被開發出來了。隨後我們就可以使用XDE的Pattern Wizard來應用定義的模式到具體的模型開發中去了。
4.6配置模式
到現在為止,我們已經完成了大部分的模式開發的工作。但是,還有一些配置問題需要解決。在Pattern Explore中,我們可以對模式進行配置,以期其能夠按照我們預想的那樣工作。
配置主要分布在兩個地方,都在Pattern Explore中以樹狀目錄顯示。具體的設置值則可在Pattern P視圖修改。一部分在模式的Advanced Properties下,還有一部分在模式中每個模版參數的Advanced Properties下。如下圖:
在這些地方,可以定制Pattern Wizard中出現的每個頁面的內容(Application Wizard Properties & Application Wizard Icons),模式的描述(Custom Dialogs),參數的生成方式(Value Source),以及約束定義(Constraints),定義事件處理(Callouts)等等。基本上所有模式的屬性,都能夠在其中定義和修改。一些更為具體的內容,可以參見後續的高級話題部分。
這樣,就基本上完成了對一個模式的設計工作,我們可以把設計好的模式,通過XDE所提供的導入/導出功能,導出為一個標准的RAS文件,供其它的開發人員使用。