天天看點

EMF介紹系列(四、枚舉類型、自定義類型和Map)

除了普通的類(接口)以外,在類圖裡可以定義一些特殊的元素,比較常見的是枚舉類型、自定義類型,它們對于一個完整可用的模型也是必不可 少的,這篇文章主要介紹EMF裡它們的使用方法。另外,由于EMF對Map的支援比較特别,是以在這裡也簡要介紹一下Map類型的定義方法。

枚舉類型

圖1 枚舉類型的屬性以下拉清單方式編輯

自定義類型

EMF雖然對大多數java類型做了包裝,但是有些情況需要我們使用沒有被包含的類型,例如在設計圖形化的編輯器(例如類圖編輯器)時,圖形節點一 般允許選擇背景顔色,這就需要一個org.eclipse.swt.graphics.RGB類型的成員變量,而RGB類是SWT提供的類,是以不能通過 建立一個同名類的方式實作,這時就要使用自定義類型。類似的道理,在必須利用遺産項目(Legacy)代碼的時候,自定義類型也是必須的。

現在為Product節點增加這樣一個名為background的成員變量,步驟如下:首先在類圖上建立一個名為RGB的自定義類型(data- type,見圖2),将它的Instance Class屬性設定為org.eclipse.swt.graphics.RGB;然後給Product類添加一個成員變量background,類型選 擇為剛建立的RGB;現在重新生成一遍代碼,可以看到Product.java裡已經多了這個成員變量,其類型為 org.eclipse.swt.graphics.RGB(因為org.eclipse.swt.graphics.RGB是屬于 org.eclipse.swt這個插件的,是以要為com.my.shop項目增加對org.eclipse.swt的依賴才能正确編譯)。

圖2 建立自定義類型

不過到這裡還沒有完成全部工作。以為EMF對這個RGB類一無所知,是以它不可能為我們實作RGB對象的持久化,即将RGB類型的資料儲存到(預設 格式的)xml檔案中。要解決這個問題得在生成的ShopFactoryImpl裡做一些定制,具體來說是修改createRGBFromString ()和convertRGBToString()這兩個方法,很明顯它們的作用分别是從字元串建立RGB對象以及将RGB對象轉換成字元串,我們把它們改為下面這樣:

這些代碼可以把RGB對象轉換為形如“255,90,150”的格式,EMF在持久化時遇到RGB類型的對象就按這樣的格式寫到檔案裡。

使用EMap

在類圖裡可以指定各種類型的成員變量,但使用Map類型則有點特别,直接定義一個EMap類型的成員變量是不可以的,因為EMap并不是繼承自 java.util.Map而是EList,也就是說EMF使用EList來模拟實作Map的功能(為什麼要這樣實作我還沒弄清楚)。要實作一個EMap 類型的成員變量,在類圖裡要參考下面的方式進行定義。

現在我們要為産品類增加一個EMap類型的屬性,用這個屬性來記錄産品每月的銷售數量,它維護一個日期字元串(如"2005-09")到當月銷售數 量的映射。首先,定義一個名為StringToIntegerMapEntry的新類,這個類将作為Map裡的項(Entry);為這個類增加兩個屬性: 字元串類型的key和整數類型(Integer或int均可)的value;在屬性視圖裡把這個類的Instance Class Name屬性設定為java.util.Map$Entry;這樣MapEntry類就定義好了,在需要EMap類型變量的類裡引用它就可以了,注 意對它的引用必須是包含關系(即“組合”而非“聚合”,類圖上連接配接線用黑色菱形修飾),并且是一對多的。

重新生成一遍代碼,在Product接口裡salesMap成員變量是這樣定義的(因為EMF會檢測到我們正在定義一個Map):

這樣,在生成的編輯器裡可以對每個産品增加新的項,每項包含key和value兩個值;在程式裡,則應該使用 Product#getSalesMap().put()方法向這個Map裡增加資料,因為我們定義的Map項是字元串到整數類型的,是以put()的時 候value參數必須是整數對象(java.lang.Integer),否則會抛出ClassCastException。請記住,不要直接指定 EMap類型,包含MapEntry即可,如果key或value不是普通類型,則使用名為key或value的引用。

圖3 編輯器裡的EMap類型屬性

圖4 修改後的模型