博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Eclipse Modeling Framework, 2nd Edition. (EMF)学习笔记(一)——EMF介绍
阅读量:5990 次
发布时间:2019-06-20

本文共 6182 字,大约阅读时间需要 20 分钟。

EMF介绍

  • 为了理解EMF究竟是什么,你只需要知道一件事:“模型”(model)是什么?“模型”的目的是什么?

  • EMF不要求全新的亦或是任何复杂的建模工具。只需要从Eclipse的Java开发工具着手开始。

  • EMF将建模概念直接与其实现相关联,所以上手比较容易。

统一Java、XML和UML

  举个编程实例,假设老板让你编写一个程序来管理供应商的采购清单。采购清单包含付款对象(bill to)和送货对象(ship to)的地址,以及货物的集合。其中,货物信息包含名称、数量、价格。

//采购清单    public intrerface PurchaseOrder    {        //送货对象        String getShipTo();        void setShipTo(String value);                //付款对象        String getBillTo();        void SetBillTo(String value);                //货物的集合        List getItems();    }
//货物信息    public intrerface Item    {        //货物名称        String getProductName();        void setProductName(String value);                //货物数量        int getQuantity();        void setQuantity(int value);        //货物价格        float getPrice();        void setPrice(float value);        }

  从上面的接口着手,你将需要开始编写应用程序的UI以及之后一系列工作。

  然而,这时候你的老板问你:“你不先建立模型吗?”尽管你觉得有点多此一举,但还是按吩咐建立了UML模型。

clipboard.png
 接下来需要保存这些“模型”,然后你决定使用XML文件来解决,于是写下了XML Schema来定义你XML文件的结构:

  在进行下一步工作前,你意识到,针对同一事物:程序的“数据模型”,你已经拥有三种不同的表示。于是你在思考:能不能只编写三者中的一种模型,其他两种从这一种模型中生成?更进一步,在这种模型中是否有足够的信息来生成接口Java实现

  于是,EMF就出现了。EMF是一个框架和代码生成工具,借助EMF这个桥梁,你可以用任意一种表示来定义一个模型,然后从中生成其他表示以及相应的实现类。下图展示了EMF是如何统一Java、XML、UML的。

clipboard.png


建模vs编程

  有个经常问到的问题:“我是该建模呢还是该编程?”,它的答案是:“都可以,建模亦或编程,这并不是问题。”在EMF看来。建模和编程可以被认为是等价的。

  对于初学者,相比于代码,建模更容易使他们描述出应用程序的功能。如果你是个经验丰富的程序员,如果对高阶建模的想法没有很大的信心,可将EMF看作建模的文雅介绍以及蕴含的优势。你不必接触一种全新的,但你也能享受的建模的一些好处。
  如果你已经了解了建模的知识,甚至是的重点,你应该讲EMF看作在那个方向的一种技术。问题是高阶建模语言还需要去学习,此外,因为我们将需要处理(例如调试)生成的Java代码,所以还需要理解它们之间的映射。优秀的传统Java编程是做这件事最简单和最直接的方式。
  我们认为,EMF将建模与编程完美地相结合,以最大限度地发挥两者的效果。
  在EMF看来,用户和其他开发者不必去了解高阶建模语言和生成的Java代码之间的映射,这些映射让Java程序员来理解是自然而又简单的。同时,应用程序之间的细粒度数据集成;代码生成产生的生产力增益,这些是建模的优势。


定义模型

Ecore(元)模型

  用于表示EMF中模型的模型称为Ecore。Ecore本身就是EMF模型,因此是它自己的元模型。也可以说Ecore是个元元模型

  元模型是模型的模型,如果该模型本身是一个元模型,那么这个元模型实际上就是元元模型。
  元模型的概念也能递归到元元元模型(meta-meta-metamodel)等等,但是我们目前用不到。
  下图给出了一个简化的Ecore元模型,说它是简化的,是因为它只是Ecore元模型的子集,而且为了方便,将某些公共类省略,如ENamedElement类(定义了类中属性的名字)。

clipboard.png

  上图中有EClass 、EAttribute 、EReference 、EDataType 四个类,这四个类都是元模型(位于的M2层)。它们的模型又都是EClass,所以位于MOF的M3层的只有EClass ,所以EClass 也是元元模型,可参考下图:

clipboard.png

  需要四种Ecore类来表示我们的模型:

  1. EClass 用于表示模型中的类,它有一个name,0个或多个attributes,0个或多个references。
  2. EAttribute 用于表示模型中的attribute,它有一个name和一个type。
  3. EReference 用于表示两个类之间的关联,它有一个name,一个布尔值表示它是否是containment,还有一个引用类型(其它类)。
  4. EDataType 用于表示attribute的类型,它可以是基本类型,例如int 、 float 或对象类型 java.util.Date等。

  从图中可以注意到Ecore类的名称和UML中的非常相似,这并不奇怪,因为UML是统一建模语言。事实上,你也许会疑惑为什么EMF模型不是UML呢?EMF为什么还需要自己专门的Ecore模型?原因就是,Ecore是UML的简化子集

  现在我们可以使用定义在Ecore中的类的实例,来描述应用程序模型中的类结构。

clipboard.png

创建和编辑模型

  你可以从你开始的任何输入形式中建立模型。如果从Java接口开始,EMF将分析并建立Ecore模型。如果从XML Schema开始,模型也将从中建立。如果从UML开始,将有三种可能性:

  1. 直接Ecore编辑。EMF有一个简单的基于树的样本编辑器
  2. 从UML导入。EMF Project和EMF Model 向导(wizard)提供一个可扩展的框架,其中有模型导入器,支持不同的模型格式。
  3. 从UML导出。类似于第二种选择,但是转换支持是由UML工具专门提供的。
  也许你会想,第一种选择是最好的,因为在开发过程中不需要导入和导出的步骤,也不必担心Ecore模型与工具本身的模型不同步。
  第二种和第三种选择的优点是,相比于EMF建模,你可以使用UML工具做得更多。

XMI序列化

  现在你也许会想Ecore模型的序列化形式是什么。上文中,这个“概念上的”模型已经被三种物理空间(Java代码、XML Schema、UML图)所表示。事实上,我们有另一种(即第四种)保存形式来作为权威性表示: 。

  为什么不适用前三种形式中的一种呢?首先,Java代码、XML Schema、UML图都具有Ecore模型不需要的额外信息,然后,它们三个中没有一个可以满足所有EMF使用的场合。采购清单模型的Ecore XMI文件如下:

  
    
    
    
  
  
    
    
    
  

要导出EMF模型时,实际上就是导出EMF的XMI。

Java注释

  EMF可以根据包含标准get()方法的接口,来生成模型属性引用。但是,EMF不会盲目地将每一个接口方法都看作模型中的一部分。只有按照EMF特定的规范才可以生成(EMF使用简单属性访问器命名模式的子集,具体规范可参考)。

  根据此规范,需要用@model标明需要用EMF生成模型的接口。例如前面给的PurchaseOrder接口就需要用下面的格式来生成UML:

/**     * @model     */    public interface PurchaseOrder    {         /**         * @model         */          String getShipTo();                   /**         * @model         */          String getBillTo();                   /**         * @model type="Item" containment="true"         */          List getItems();    }

  @model标签是来将PurchaseOrder 标识为一个需要被建模的类。

  shipTo和billTo的类型是String,所以在@model标签之后没有额外的模型信息
  getItems()返回的是一个对象类型为Item的List,所以需要在@model标签之后加上type="Item"。此外,因为getItems()是货物的容器并会在其中将货物作为孩子序列化,所以需要标识出containment="true"
  从Java 5.0 开始,可以被用来指定List中对象的类型,从EMF 2.3开始,也可以支持泛型。
  我们注意得到在接口PurchaseOrder中没有定义 setShipTo()setBillTo()方法,因为在EMF看来,只要get()方法的上面有注释,如果没有相应的set()方法,EMF就会自动生成set()方法并整合到接口中。

Ecore“蓝图”

  我们回顾一下前面的知识。

  - EcoreXMI序列化,是EMF的核心
  - Ecore模型的创建,有至少三种方式:UML模型XML Schema注释后的Java接口
  - Ecore模型可以生成 Java 接口的实现代码以及模型的其他形式
  使用XML Schema定义模型有个重要的优点:根据schema,可以序列化模型的实例来符合模型。除了简单地定义模型,XML Schema也能指定模型实例的持久形式
  这里有个问题:“是否有其他持久形式?”答案是肯定的。例如 Schema。“蓝图”如下:

clipboard.png


生成代码

  EMF最大的优点就是自动生成代码的效率很高。现在,在前面的基础上,你只需要使用EMF Project 向导(自动加载了生成器)来创建项目,然后在菜单上选择Generate Model Code

生成的模型类

  EMF生成的代码是什么样的呢?

  首先,Ecore类(比如一个EClass)对应Java中的接口以及其实现类。举例子来说,PurchaseOrder的EClass对应的Java接口:

public interface PurchaseOrder ...

  这个接口对应的实现类:

public class PurchaseOrderImpl extends ... implements PurchaseOrder {

  这种接口-实现两者分离(interface–implementation)是EMF青睐的设计选择。因为这是任何一个类模型API(model-like API)最好的模式。例如,是这样的,Eclipse的许多API也是如此。它也是支持Java中的必要模式。

  其次,每个生成的接口都直接或间接扩展了基接口EObject

public interface PurchaseOrder extends EObject {

  EMF中的EObject等价于java.lang.Object,它是所有建模对象的基础。扩展的EObject引入了以下三种主要行为:

  1. eClass()返回对象的元对象(一个EClass)。
  2. eContainer()eResource() 返回的是对象里面包含的对象和资源
  3. eGet()eSet()eIsSet(),和eUnset()提供一个API,用来反射式访问对象。
  然后,EObject还是另一个接口Notifier的扩展:

public interface EObject extends Notifier {

  Notifier接口向建模对象中引入一个重要的特性:模型变更通知(notification),正如在中。和对象持久性一样,通知也是EMF对象的一个重要特征。

  最后,根据类型及用户设定的属性生成方法以及方法中的实例变量。例如:

public String getShipTo()    {        return shipTo;    }

  EMF会自动生成对应的set()方法并设置相同的变量,但是set()方法也会发送一个通知给任何可能对状态变更感兴趣的观察者,如下:

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));    }

  可以看到,为了使方法更高效,当没有观察者时,为了避免调用eNotify()花费的高昂代价,EMF会添加一个eNotificationRequired()守卫条件。

转载地址:http://mvnlx.baihongyu.com/

你可能感兴趣的文章
java----加密/解密常用算法
查看>>
BSON
查看>>
未安装SqlServer,打开.mdf文件的方法
查看>>
动态顺序表
查看>>
面试题——栈与队列的应用(上)
查看>>
ajax请求得到后台数据,前台页面不用拼接 “字符串和HTML表格标签”,使用方便模板然后clone,显示表格...
查看>>
视频会议管理接口
查看>>
《计算机科学导论》安全基础知识
查看>>
如何制作WIN TO GO
查看>>
tomcat停止出现内存泄漏
查看>>
理解 Python Tornado 的 `non-blocking`
查看>>
AOPR如何快速打开文件的方法
查看>>
常见的软件测试面试问题~
查看>>
RabbitMQ 三种Exchange
查看>>
ios 支付宝支付流程
查看>>
js删除数组里的某个元素
查看>>
进程管理学习笔记
查看>>
分析逻辑
查看>>
手机大厂开始走上AI芯片 将来掀起AI应用
查看>>
Linux -管道符和作业控制
查看>>