Eclipse Modeling Framework, 2nd Edition. (EMF)学习笔记(一)——EMF介绍
EMF介紹
為了理解EMF究竟是什么,你只需要知道一件事:“模型”(model)是什么?“模型”的目的是什么?
EMF不要求全新的方法論亦或是任何復(fù)雜的建模工具。只需要從Eclipse的Java開(kāi)發(fā)工具著手開(kāi)始。
EMF將建模概念直接與其實(shí)現(xiàn)相關(guān)聯(lián),所以上手比較容易。
統(tǒng)一Java、XML和UML
舉個(gè)編程實(shí)例,假設(shè)老板讓你編寫一個(gè)程序來(lái)管理供應(yīng)商的采購(gòu)清單。采購(gòu)清單包含付款對(duì)象(bill to)和送貨對(duì)象(ship to)的地址,以及貨物的集合。其中,貨物信息包含名稱、數(shù)量、價(jià)格。
//采購(gòu)清單public intrerface PurchaseOrder{//送貨對(duì)象String getShipTo();void setShipTo(String value);//付款對(duì)象String getBillTo();void SetBillTo(String value);//貨物的集合List getItems();} //貨物信息public intrerface Item{//貨物名稱String getProductName();void setProductName(String value);//貨物數(shù)量int getQuantity();void setQuantity(int value);//貨物價(jià)格float getPrice();void setPrice(float value); }從上面的接口著手,你將需要開(kāi)始編寫應(yīng)用程序的UI以及之后一系列工作。
然而,這時(shí)候你的老板問(wèn)你:“你不先建立模型嗎?”盡管你覺(jué)得有點(diǎn)多此一舉,但還是按吩咐建立了UML模型。
接下來(lái)需要保存這些“模型”,然后你決定使用XML文件來(lái)解決,于是寫下了XML Schema來(lái)定義你XML文件的結(jié)構(gòu):
在進(jìn)行下一步工作前,你意識(shí)到,針對(duì)同一事物:程序的“數(shù)據(jù)模型”,你已經(jīng)擁有三種不同的表示。于是你在思考:能不能只編寫三者中的一種模型,其他兩種從這一種模型中生成?更進(jìn)一步,在這種模型中是否有足夠的信息來(lái)生成接口的Java實(shí)現(xiàn)。
于是,EMF就出現(xiàn)了。EMF是一個(gè)框架和代碼生成工具,借助EMF這個(gè)橋梁,你可以用任意一種表示來(lái)定義一個(gè)模型,然后從中生成其他表示以及相應(yīng)的實(shí)現(xiàn)類。下圖展示了EMF是如何統(tǒng)一Java、XML、UML的。
建模vs編程
有個(gè)經(jīng)常問(wèn)到的問(wèn)題:“我是該建模呢還是該編程?”,它的答案是:“都可以,建模亦或編程,這并不是問(wèn)題?!痹贓MF看來(lái)。建模和編程可以被認(rèn)為是等價(jià)的。
對(duì)于初學(xué)者,相比于代碼,建模更容易使他們描述出應(yīng)用程序的功能。如果你是個(gè)經(jīng)驗(yàn)豐富的程序員,如果對(duì)高階建模的想法沒(méi)有很大的信心,可將EMF看作建模的文雅介紹以及蘊(yùn)含的優(yōu)勢(shì)。你不必接觸一種全新的方法論,但你也能享受的建模的一些好處。
如果你已經(jīng)了解了建模的知識(shí),甚至是MDA的重點(diǎn),你應(yīng)該講EMF看作在那個(gè)方向的一種技術(shù)。問(wèn)題是高階建模語(yǔ)言還需要去學(xué)習(xí),此外,因?yàn)槲覀儗⑿枰幚?#xff08;例如調(diào)試)生成的Java代碼,所以還需要理解它們之間的映射。優(yōu)秀的傳統(tǒng)Java編程是做這件事最簡(jiǎn)單和最直接的方式。
我們認(rèn)為,EMF將建模與編程完美地相結(jié)合,以最大限度地發(fā)揮兩者的效果。
在EMF看來(lái),用戶和其他開(kāi)發(fā)者不必去了解高階建模語(yǔ)言和生成的Java代碼之間的映射,這些映射讓Java程序員來(lái)理解是自然而又簡(jiǎn)單的。同時(shí),應(yīng)用程序之間的細(xì)粒度數(shù)據(jù)集成;代碼生成產(chǎn)生的生產(chǎn)力增益,這些是建模的優(yōu)勢(shì)。
定義模型
Ecore(元)模型
用于表示EMF中模型的模型稱為Ecore。Ecore本身就是EMF模型,因此是它自己的元模型。也可以說(shuō)Ecore是個(gè)元元模型。
元模型是模型的模型,如果該模型本身是一個(gè)元模型,那么這個(gè)元模型實(shí)際上就是元元模型。
元模型的概念也能遞歸到元元元模型(meta-meta-metamodel)等等,但是我們目前用不到。
下圖給出了一個(gè)簡(jiǎn)化的Ecore元模型,說(shuō)它是簡(jiǎn)化的,是因?yàn)樗皇荅core元模型的子集,而且為了方便,將某些公共類省略,如ENamedElement類(定義了類中屬性的名字)。
上圖中有EClass 、EAttribute 、EReference 、EDataType 四個(gè)類,這四個(gè)類都是元模型(位于MOF的M2層)。它們的模型又都是EClass,所以位于MOF的M3層的只有EClass ,所以EClass 也是元元模型,可參考下圖:
需要四種Ecore類來(lái)表示我們的模型:
1. EClass 用于表示模型中的類,它有一個(gè)name,0個(gè)或多個(gè)attributes,0個(gè)或多個(gè)references。
2. EAttribute 用于表示模型中的attribute,它有一個(gè)name和一個(gè)type。
3. EReference 用于表示兩個(gè)類之間的關(guān)聯(lián),它有一個(gè)name,一個(gè)布爾值表示它是否是containment,還有一個(gè)引用類型(其它類)。
4. EDataType 用于表示attribute的類型,它可以是基本類型,例如int 、 float 或?qū)ο箢愋?java.util.Date等。
從圖中可以注意到Ecore類的名稱和UML中的非常相似,這并不奇怪,因?yàn)閁ML是統(tǒng)一建模語(yǔ)言。事實(shí)上,你也許會(huì)疑惑為什么EMF模型不是UML呢?EMF為什么還需要自己專門的Ecore模型?原因就是,Ecore是UML的簡(jiǎn)化子集。
現(xiàn)在我們可以使用定義在Ecore中的類的實(shí)例,來(lái)描述應(yīng)用程序模型中的類結(jié)構(gòu)。
創(chuàng)建和編輯模型
你可以從你開(kāi)始的任何輸入形式中建立模型。如果從Java接口開(kāi)始,EMF將分析并建立Ecore模型。如果從XML Schema開(kāi)始,模型也將從中建立。如果從UML開(kāi)始,將有三種可能性:
1. 直接Ecore編輯。EMF有一個(gè)簡(jiǎn)單的基于樹的樣本編輯器。
2. 從UML導(dǎo)入。EMF Project和EMF Model 向?qū)?#xff08;wizard)提供一個(gè)可擴(kuò)展的框架,其中有模型導(dǎo)入器,支持不同的模型格式。
3. 從UML導(dǎo)出。類似于第二種選擇,但是轉(zhuǎn)換支持是由UML工具專門提供的。
也許你會(huì)想,第一種選擇是最好的,因?yàn)樵陂_(kāi)發(fā)過(guò)程中不需要導(dǎo)入和導(dǎo)出的步驟,也不必?fù)?dān)心Ecore模型與工具本身的模型不同步。
第二種和第三種選擇的優(yōu)點(diǎn)是,相比于EMF建模,你可以使用UML工具做得更多。
XMI序列化
現(xiàn)在你也許會(huì)想Ecore模型的序列化形式是什么。上文中,這個(gè)“概念上的”模型已經(jīng)被三種物理空間(Java代碼、XML Schema、UML圖)所表示。事實(shí)上,我們有另一種(即第四種)保存形式來(lái)作為權(quán)威性表示: XML Metadata Interchange (XMI)。
為什么不適用前三種形式中的一種呢?首先,Java代碼、XML Schema、UML圖都具有Ecore模型不需要的額外信息,然后,它們?nèi)齻€(gè)中沒(méi)有一個(gè)可以滿足所有EMF使用的場(chǎng)合。采購(gòu)清單模型的Ecore XMI文件如下:
要導(dǎo)出EMF模型時(shí),實(shí)際上就是導(dǎo)出EMF的XMI。
Java注釋
EMF可以根據(jù)包含標(biāo)準(zhǔn)get()方法的接口,來(lái)生成模型屬性和引用。但是,EMF不會(huì)盲目地將每一個(gè)接口和方法都看作模型中的一部分。只有按照EMF特定的規(guī)范才可以生成(EMF使用JavaBeans簡(jiǎn)單屬性訪問(wèn)器命名模式的子集,具體規(guī)范可參考http://java.sun.com/products/...)。
根據(jù)此規(guī)范,需要用@model標(biāo)明需要用EMF生成模型的接口。例如前面給的PurchaseOrder接口就需要用下面的格式來(lái)生成UML:
@model標(biāo)簽是來(lái)將PurchaseOrder 標(biāo)識(shí)為一個(gè)需要被建模的類。
shipTo和billTo的類型是String,所以在@model標(biāo)簽之后沒(méi)有額外的模型信息。
getItems()返回的是一個(gè)對(duì)象類型為Item的List,所以需要在@model標(biāo)簽之后加上type="Item"。此外,因?yàn)間etItems()是貨物的容器并會(huì)在其中將貨物作為孩子序列化,所以需要標(biāo)識(shí)出containment="true"。
從Java 5.0 開(kāi)始,泛型可以被用來(lái)指定List中對(duì)象的類型,從EMF 2.3開(kāi)始,也可以支持泛型。
我們注意得到在接口PurchaseOrder中沒(méi)有定義 setShipTo()和setBillTo()方法,因?yàn)樵贓MF看來(lái),只要get()方法的上面有注釋,如果沒(méi)有相應(yīng)的set()方法,EMF就會(huì)自動(dòng)生成set()方法并整合到接口中。
Ecore“藍(lán)圖”
我們回顧一下前面的知識(shí)。
- Ecore和XMI序列化,是EMF的核心。
- Ecore模型的創(chuàng)建,有至少三種方式:UML模型、XML Schema、注釋后的Java接口。
- Ecore模型可以生成 Java 接口的實(shí)現(xiàn)代碼以及模型的其他形式。
使用XML Schema來(lái)定義模型有個(gè)重要的優(yōu)點(diǎn):根據(jù)schema,可以序列化模型的實(shí)例來(lái)符合模型。除了簡(jiǎn)單地定義模型,XML Schema也能指定模型實(shí)例的持久形式。
這里有個(gè)問(wèn)題:“是否有其他持久形式?”答案是肯定的。例如RDB Schema?!八{(lán)圖”如下:
生成代碼
EMF最大的優(yōu)點(diǎn)就是自動(dòng)生成代碼的效率很高?,F(xiàn)在,在前面的基礎(chǔ)上,你只需要使用EMF Project 向?qū)?/strong>(自動(dòng)加載了生成器)來(lái)創(chuàng)建項(xiàng)目,然后在菜單上選擇Generate Model Code。
生成的模型類
EMF生成的代碼是什么樣的呢?
首先,Ecore類(比如一個(gè)EClass)對(duì)應(yīng)Java中的接口以及其實(shí)現(xiàn)類。舉例子來(lái)說(shuō),PurchaseOrder的EClass對(duì)應(yīng)的Java接口:
這個(gè)接口對(duì)應(yīng)的實(shí)現(xiàn)類:
public class PurchaseOrderImpl extends ... implements PurchaseOrder { 這種接口-實(shí)現(xiàn)兩者分離(interface–implementation)是EMF青睞的設(shè)計(jì)選擇。因?yàn)檫@是任何一個(gè)類模型API(model-like API)最好的模式。例如,文檔對(duì)象模式(DOM)是這樣的,Eclipse的許多API也是如此。它也是支持Java中多重繼承的必要模式。
其次,每個(gè)生成的接口都直接或間接擴(kuò)展了基接口EObject:
EMF中的EObject等價(jià)于java.lang.Object,它是所有建模對(duì)象的基礎(chǔ)。擴(kuò)展的EObject引入了以下三種主要行為:
1. eClass()返回對(duì)象的元對(duì)象(一個(gè)EClass)。
2. eContainer()和eResource() 返回的是對(duì)象里面包含的對(duì)象和資源。
3. eGet()、eSet()、eIsSet(),和eUnset()提供一個(gè)API,用來(lái)反射式訪問(wèn)對(duì)象。
然后,EObject還是另一個(gè)接口Notifier的擴(kuò)展:
Notifier接口向建模對(duì)象中引入一個(gè)重要的特性:模型變更通知(notification),正如在觀察者模式(Observer design pattern)中。和對(duì)象持久性一樣,通知也是EMF對(duì)象的一個(gè)重要特征。
最后,根據(jù)類型及用戶設(shè)定的屬性生成方法以及方法中的實(shí)例變量。例如:
EMF會(huì)自動(dòng)生成對(duì)應(yīng)的set()方法并設(shè)置相同的變量,但是set()方法也會(huì)發(fā)送一個(gè)通知給任何可能對(duì)狀態(tài)變更感興趣的觀察者,如下:
public void setShipTo(String newShipTo){String oldShipTo = shipTo;shipTo = newShipTo;if (eNotificationRequired())eNotify(new ENotificationImpl(this,Notification.SET,POPackage.PURCHASE_ORDER__SHIP_TO,oldShipTo, shipTo));}可以看到,為了使方法更高效,當(dāng)沒(méi)有觀察者時(shí),為了避免調(diào)用eNotify()花費(fèi)的高昂代價(jià),EMF會(huì)添加一個(gè)eNotificationRequired()守衛(wèi)條件。
總結(jié)
以上是生活随笔為你收集整理的Eclipse Modeling Framework, 2nd Edition. (EMF)学习笔记(一)——EMF介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: zhlan--Python中的字典遍历方
- 下一篇: 在使用chrome调试angular2的