亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

用模型驅(qū)動(dòng)Eclipse開(kāi)發(fā) ( by quqi99 )

系統(tǒng) 2077 0

用模型驅(qū)動(dòng)Eclipse開(kāi)發(fā) ( by quqi99 )

EMF(Eclipse Modeling Framework)是一個(gè)模型架構(gòu)和代碼生成工具,它可以用來(lái)建構(gòu)以結(jié)構(gòu)化數(shù)據(jù)為基礎(chǔ)的工具或者應(yīng)用。作為MDA和Eclipse的結(jié)合體,它發(fā)展迅速,IBM的大部分工具產(chǎn)品如RSA等都將建立在它的基礎(chǔ)之上。

樣例

我們將構(gòu)建一個(gè)簡(jiǎn)單的手機(jī)庫(kù)管工具,它只維護(hù)種類(lèi)信息,并不存儲(chǔ)數(shù)量庫(kù)位等。通過(guò)該工具,我們可以添加,刪除,修改主機(jī)及配件;維護(hù)主機(jī),配件的功能;并且可以通過(guò)拖放將主機(jī)和相關(guān)配件組成一種配置。

建立模型

 EMF通過(guò)JET和JMERGE來(lái)實(shí)現(xiàn)支持MDA,它可以從annotated Java, UML, or XML Schema三種模型生成Eclipse plug-in代碼。我們將用Rational Rose建立UML模型來(lái)作為系統(tǒng)模型。

用模型驅(qū)動(dòng)Eclipse開(kāi)發(fā) ( by quqi99 )
  圖1:簡(jiǎn)單的手機(jī)庫(kù)管工具的UML模型表示

將模型導(dǎo)入Eclipse中

建立EMF工程,在Wizard中會(huì)提示選擇初始化的模型內(nèi)容。從Rose中讀取類(lèi)模型以后,將生成了一個(gè)工程,其中包含兩個(gè)文件:.ecore和.genmodel。

Ecore文件代表我們的模型本身,你可以通過(guò)修改它來(lái)改變模型。比如改變屬性的類(lèi)型,類(lèi)之間的關(guān)系等。你也完全可以通過(guò)手動(dòng)的方式建立ecore文件來(lái)創(chuàng)建整個(gè)模型。我們可以看到,在ecore模型中,所有的類(lèi)被轉(zhuǎn)換為EClass;聚合關(guān)系變成了一個(gè)EClass包含其它EClass作為EReference,例如主機(jī)、配置、配件都作為庫(kù)存的EReference。在這里,我們需要修改EReference的Containment屬性,缺省的值是false。Containment屬性是在持久化時(shí)的一個(gè)重要屬性,它表明存儲(chǔ)時(shí)數(shù)據(jù)的包含關(guān)系,如果全部保留為fasle,將不會(huì)有任何信息被存儲(chǔ)到文件中,除了頂級(jí)節(jié)點(diǎn):庫(kù)存。應(yīng)該以誰(shuí)創(chuàng)建,誰(shuí)包含為原則。比如庫(kù)存可以創(chuàng)建主機(jī)、配件、配置,那么這些庫(kù)存的EReference的Containment屬性都應(yīng)該設(shè)為true;而配置并不負(fù)責(zé)創(chuàng)建主機(jī)和配件,只是從庫(kù)存中現(xiàn)有的主機(jī)和配件拖放過(guò)來(lái)的,那么它下面的主機(jī),配件EReference的Containment屬性都應(yīng)該為false。

 以XMI存儲(chǔ)為例,修改后存儲(chǔ)的格式應(yīng)該為:

<?xml version="1.0" encoding="UTF-8"?>
<mobiles:庫(kù)存 xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:mobiles="http:///mobiles.ecore">
<配置 配件="http://@配件.0" 主機(jī)="http://@主機(jī).0"/>
<配件>
<功能/>
</配件>
<主機(jī)>
<功能/>
</主機(jī)>
</mobiles:庫(kù)存>

Genmodel文件主要維護(hù)著一些與生成代碼相關(guān)的設(shè)置,比如說(shuō),某個(gè)屬性可不可以修改。大部分的屬性都不用修改,我們要決定的仍然是EReference的屬性:Children,Create Child,Notify。

Notify是表明它應(yīng)不應(yīng)該將在這個(gè)包含節(jié)點(diǎn)中有關(guān)自身的改變通知給其它的相同節(jié)點(diǎn)。比如某個(gè)主機(jī)V3在庫(kù)存中創(chuàng)建之后被拖到某個(gè)配置里,這樣在整個(gè)樹(shù)上就存在兩個(gè)V3:一個(gè)是V3本身,另一個(gè)是它的一個(gè)引用。如果將配置中主機(jī)的Notify屬性設(shè)為true后,改變配置中引用的V3價(jià)格,它就會(huì)把這個(gè)改變通知給V3自身,實(shí)現(xiàn)同步。通常情況下應(yīng)將所有的EReference的Notify設(shè)為true。

按照下表做出設(shè)置:

包含節(jié)點(diǎn) EReference Children Create Child Notify
庫(kù)存 主機(jī)
配件
配置 True True True
主機(jī) 功能 True True True
主機(jī) 配件 True False True
配件 功能 True True True
配置 主機(jī)
配件 True False True

生成代碼并運(yùn)行

用EMF generator(缺省的Eidtor)打開(kāi)genmodel文件,原來(lái)的工程中會(huì)生成Model代碼,兩個(gè)新的工程Edit和Editor工程會(huì)被生成, Edit工程包含了一些方便編輯Model的代碼,Eidtor工程中大都是UI部分的代碼,不在本文范圍之內(nèi)。

.mobiles文件生成后,將會(huì)用Mobiles Model Editor打開(kāi)。現(xiàn)在就可以在庫(kù)存中添加主機(jī)配件等,并將其拖到某個(gè)配置中去。這里所謂的Mobiles在缺省情況下與你的Rose文件的名字相同,在Editor工程的Plugin.xml的editor擴(kuò)展中可以看到生成的后綴。

用模型驅(qū)動(dòng)Eclipse開(kāi)發(fā) ( by quqi99 )

 Model Plug-in

EMF是從作為MOF規(guī)范在Eclipse的一個(gè)實(shí)現(xiàn)開(kāi)始的,隨后通過(guò)大量的運(yùn)用在工具的實(shí)現(xiàn),EMF成為一個(gè)有效的MOF API的一個(gè)核心子集的Java實(shí)現(xiàn)。EMF中的元數(shù)據(jù)被稱(chēng)為Ecore。

用模型驅(qū)動(dòng)Eclipse開(kāi)發(fā) ( by quqi99 )
 灰色的類(lèi)代表抽象類(lèi),所有的類(lèi)都繼承自Eobject。EPackage包含關(guān)于模型類(lèi)(EClass)和數(shù)據(jù)類(lèi)型(EDataType)的信息。EClass描述一個(gè)建模的類(lèi),并且指定屬性和參考以描述實(shí)例的數(shù)據(jù)。EAttribute描述簡(jiǎn)單數(shù)據(jù),它由一個(gè)EDataType來(lái)指定。EReference描述一個(gè)類(lèi)之間的關(guān)聯(lián);它的類(lèi)型是一個(gè)Eclass。EFactory包含創(chuàng)建模型元素的方法。更多的關(guān)于Ecore的描述請(qǐng)參考Eclipse官方網(wǎng)站。
包和工廠
前面說(shuō)過(guò)EPackage包含所有關(guān)于EClass和EDataType的信息,參看生成的代碼mobiles. MobilesPackage,可以看到Eclass的feature ID聲明:

int 主機(jī) = 0;
 int 配置 = 1;

feature ID僅僅是對(duì)所有的類(lèi)元素(不包含類(lèi)型信息)的一個(gè)int類(lèi)型的編號(hào),有了它可以使你很快的區(qū)分出是哪個(gè)類(lèi)的哪個(gè)屬性。例如在某個(gè)類(lèi)的屬性值發(fā)生改變后,它的監(jiān)聽(tīng)者會(huì)收到一個(gè)通知,通知里就包含了改變了的屬性的feature ID,這時(shí)你就可以簡(jiǎn)單的通過(guò)一個(gè)switch方法來(lái)實(shí)現(xiàn)分派。

MobilesPackage中另外的一些是關(guān)于類(lèi)型的,例如:

EClass get主機(jī)();
 EAttribute get主機(jī)_Name();

在某些情況下這些元數(shù)據(jù)是非常重要的,比如在決定某個(gè)屬性的編輯框類(lèi)型的時(shí)候。當(dāng)然你也可以直接調(diào)用某個(gè)類(lèi)型的create方法來(lái)創(chuàng)建對(duì)象:

適配器

EMF最重要的一個(gè)特性就是它對(duì)Adapter的定義。在EMF中Adapter有兩個(gè)功能,第一個(gè)是類(lèi)似于Observer的功能,它可以監(jiān)聽(tīng)目標(biāo)對(duì)象的變化然后做出相應(yīng)的反映;另一個(gè)是通過(guò)它可以使目標(biāo)對(duì)象不用繼承某個(gè)接口或者父類(lèi)來(lái)實(shí)現(xiàn)其特有的功能。這一節(jié)我們會(huì)結(jié)合Model Plug_in的代碼來(lái)探討Adapter的這兩個(gè)功能。

Observer

通常的Observer模式需要至少兩個(gè)類(lèi),監(jiān)聽(tīng)者和目標(biāo)對(duì)象。EMF中,監(jiān)聽(tīng)者稱(chēng)為Adapter,目標(biāo)對(duì)象稱(chēng)為Notifier。每個(gè)Notifier都擁有一個(gè)eAdapters列表,維護(hù)著所有監(jiān)聽(tīng)者的類(lèi)型,一旦Notifier發(fā)生變化,它會(huì)遍歷eAdapters列表將變化通知給列表中的每一個(gè)Adapter。所以假如某個(gè)Adapter想要監(jiān)聽(tīng)這個(gè)Notifier,只需要將自己添加到Notifier的eAdapters中。

EMF中所有的對(duì)象都直接或間接繼承自Eobject,如同java中所有的類(lèi)都繼承自O(shè)bject一樣。而Eobject類(lèi)已經(jīng)實(shí)現(xiàn)了Notifier接口,所以所有的EMF的類(lèi)都可以是Notifier。

Adapter需要自己來(lái)實(shí)現(xiàn)AdapterImpl,需要實(shí)現(xiàn)的方法主要有兩個(gè),isAdapterForType和notifyChanged。IsAdapterForType是用來(lái)判斷這個(gè)Adapter能不能監(jiān)聽(tīng)某個(gè)Notifier,notifyChanged包含著一旦Notifier發(fā)生了變化這個(gè)Adapter所要做出的所有相應(yīng)。假設(shè)我們需要一個(gè)Adapter,它來(lái)監(jiān)聽(tīng)主機(jī)的變化,一旦任何關(guān)于主機(jī)的增刪改操作產(chǎn)生就將改變記錄在本地文件中。

Notification類(lèi)是由Notifier發(fā)出來(lái)的,它包含著發(fā)出者getNotifier(),改變之前的舊值getOldValue()和改變后的新值getNewValue()。象如下示例這樣使用這個(gè)Adapter:

主機(jī) machine= MobilesFactory. EINSTANCE. create主機(jī)();
 主機(jī)Adapter adapter = new主機(jī)Adapter();
 machine.eAdatpters().add(adapter);
 machine.setName(“V3”);

你要自己實(shí)例化Adapter,并且把它添加到Notifier的eAdaters里去。假如在其它的某個(gè)地方你有同樣的需求,但你不確定“主機(jī)Adapter”是否已經(jīng)被添加到“主機(jī)”的eAdatpters里了,你就需要遍歷現(xiàn)有的adapter,來(lái)判斷是否已被添加。然后決定創(chuàng)不創(chuàng)建新的“主機(jī)Adapter”。事實(shí)上EMF提供了AdapterFactory來(lái)簡(jiǎn)化你的工作。可以參照生成的代碼mobiles.util. MobilesAdapterFactory.java。它只是一個(gè)框架,用來(lái)根據(jù)Notifier的類(lèi)型生成相應(yīng)的Adatpter并將其注冊(cè)到Notifier的eAdapters列表中去。它還借用了MobilesSwitch類(lèi)的分派功能。

 MobilesSwitch只做了一件事情,那就是根據(jù)Notifier的類(lèi)型調(diào)用不同的case*方法。例如,如果Notifier是“主機(jī)”,它會(huì)去調(diào)用case主機(jī)()方法。MobilesAdapterFactory中則實(shí)現(xiàn)了case主機(jī)()方法,調(diào)用create主機(jī)Adapter()來(lái)創(chuàng)建“主機(jī)Adapter”。

繼續(xù)上面的例子,我們實(shí)現(xiàn)一個(gè)AdapterFactory:

public class MobilesAdapterFactoryImpl extends MobilesAdapterFactory{
public static MobilesAdapterFactoryImpl
INSTANCE = new MobilesAdapterFactoryImpl ();
public Adapter create主機(jī)Adapter() {
return new主機(jī)Adapter();
}
}

用的時(shí)候就很簡(jiǎn)單:

主機(jī) machine= MobilesFactory. EINSTANCE. create主機(jī)();
MobilesAdapterFactoryImpl.INSTANCE.adapt(machine, 主機(jī)Adapter.class);
machine.setName(“V3”);

factory會(huì)遍歷machine的eAdapters,如果沒(méi)有“主機(jī)Adapter”則創(chuàng)建一個(gè)添加進(jìn)去,否則返回已有的。

行為擴(kuò)展
 我們把日志功能提取出來(lái),成為一個(gè)類(lèi):

public interface Logger{
public void log();
}

其實(shí)我們希望的是“主機(jī)”也能有日志功能,可以在自己改變之后將變化記錄下來(lái)。以往我們要做的就是讓“主機(jī)”繼承Logger,然后實(shí)現(xiàn)log()方法記錄下自己這種特定類(lèi)型的信息。但有的時(shí)候通過(guò)繼承來(lái)擴(kuò)展行為并不是那么舒服,比如繼承的關(guān)系是死的,你不能在你不需要的時(shí)候去掉這些擴(kuò)展行為。通過(guò)Adapter你可以隨心所欲的控制這些擴(kuò)展行為。

public class 主機(jī)Adapter extends AdapterImpl implements Logger
{
public void notifyChanged(Notification notification) {
if (notification.getNotifier() instanceof 主機(jī))
log();
}

public boolean isAdapterForType(Object type) {
return type == 主機(jī).class;
}
public void log(){
//log the name, band,year,changed property name and its old value and new value
}
}

用的時(shí)候同上邊一樣:

主機(jī) machine= MobilesFactory. EINSTANCE. create主機(jī)();
MobilesAdapterFactoryImpl.INSTANCE.adapt(machine, 主機(jī)Adapter.class);
machine.setName(“V3”);

這個(gè)時(shí)候任何“主機(jī)”的變化都會(huì)引起“主機(jī)Adapter”執(zhí)行擴(kuò)展了的log()方法,這一點(diǎn)與AOP很像。

Model Class

 我們現(xiàn)在把目光關(guān)注到Model Plug_in中最重要的部分。首先是Model的接口,例如接口“主機(jī)”,它的定義非常簡(jiǎn)單,就是些屬性的get,set方法。get方法很簡(jiǎn)單,而set方法則比較有趣:

public void setName(String newName) {
String oldName = name;
name = newName;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this,
Notification.SET,
MobilesPackage.主機(jī)__NAME,
oldName, name));
}

它不僅僅將類(lèi)變量賦予了新值,還在需要Notify的時(shí)候發(fā)出了一個(gè)Notification。如同上一節(jié)所講的,這個(gè)Notification將包含發(fā)出者,改變的方式,改變的屬性標(biāo)識(shí)(feature ID)、舊值和新值。

 隨后是一些e開(kāi)頭的方法,他們都是用作反射的。例如eGet,根據(jù)feature ID返回相應(yīng)的屬性值;eSet,根據(jù)feature ID設(shè)置相應(yīng)的屬性值;eUnset,根據(jù)feature ID設(shè)置相應(yīng)的屬性值為缺省值;eIsSet,根據(jù)feature ID判斷相應(yīng)的屬性是否被設(shè)置過(guò);

限于篇幅的關(guān)系,EMF中還有很多高級(jí)的功能沒(méi)有在本文中介紹,比如持久化,Command pattern等;Edit工程里更是包含了集萬(wàn)千寵愛(ài)于一身的ItemProvider,它們都非常重要,希望以后有機(jī)會(huì)能與讀者共同探討

用模型驅(qū)動(dòng)Eclipse開(kāi)發(fā) ( by quqi99 )


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 午夜欧美精品久久久久久久久 | 久久精品国产99久久72 | 国产精品久久久久桃色tv | 抱着cao才爽视频 | 欧美一级在线毛片免费观看 | 资源站在线 | 国产一区二区免费在线观看 | 色香视频在线 | 欧美午夜精品久久久久免费视 | 特黄aaaaaaaaa真人毛片 | 激情开心婷婷 | 久久99精品久久久久久黑人 | 欧美日韩在线成人免费 | 大陆国产精品视频 | 久草最新网址 | 亚洲国产欧洲 | 精品久久久日韩精品成人 | 羞羞视频免费网站在线 | 日韩女人毛片在线播放 | 女人zzzooooxxxx| 99re热视频精品首页 | 2021福利视频 | 成人短视频在线观看 | 日韩在线1 | 国产欧美日韩免费一区二区 | 九九热这里只有精品6 | 精品动漫一区二区三区 | 天天爽夜夜操 | 欧美久久久久欧美一区 | 日韩日b视频 | 99国产成人高清在线视频 | 中国一级特黄高清免费的大片 | 欧美成人性色生活片天天看 | 国产综合视频 | 国产免费久久精品99久久 | 在线视频亚洲一区 | 久草热视频在线 | 亚洲精品国产啊女成拍色拍 | 综合久久久久综合 | 五月天色区 | 伊人精品影院一本到欧美 |