EMF学习笔记3——EMF命令

本文介绍如何在EMF中使用EditingDomain接口编辑模型,包括两种删除模型元素的方法:直接操作和使用命令。详细解释了如何利用命令来增强操作的可撤销性和可重用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在EMF中可以通过EditingDomain接口来编辑模型。
AdapterFactoryEditingDomain实现了EditingDomain接口,和AdaperFactoryContentProvider一样,将操作逻辑通过适配器工厂转接给适配器类进行处理。通过AdapterFacotryEditingDomain还可以访问CommandStack对象,所有对模型结构的修改命令都将存储在这里。

更改模型结构的方法:
假设两个EMF实体类Companny和Department属于1对多关系,现在公司想删除指定部门,可通过以下几个方法来完成操作:

1.不使用命令的普通方式
Department d=... Company c=... c.getDepartments().remove(d);

因为所有的Emf实体都间接的实现了Notifier接口,因此在执行remove操作时,EMF的通知机制可以将模型结构的变动及时反映到视图组件的刷新.(稍后会详写这里)

2.使用org.eclipse.emf.edit.command.RemoveCommand命令来执行删除操作
Department d=... Company c=... EditingDomain ed=... RemoveCommand cmd=new RemoveCommand(ed,c,CompanyPackage.eINSTANCE.getCompany_Departments(),d); ed.getCommandStack().execute(cmd);

通过命令的方式执行虽然代码逻辑较多,但有以下好处:
1.对已执行出的命令执行撤销操作(undo,redo)
2.可判断模型结构是否被修改(用来触发save操作)
3.可判断一个命令是否可执行

直接new一个命令出来,这个命令是有针对性的(如:这里的命令只针对company实体),因此可重用性比较低,我们可以通过EditingDomain接口的createCommand()方法来创建命令,来使这个命令针对所有模型实体通用。
createCommand(Class commandClass, CommandParameter commandParameter)这个方法有两个参数:
commandClass:为具体的命令类,如org.eclipse.emf.edit.command.RemoveCommand
commandParameter:为命令参数,通过此种方式,可编写如下代码:
Department d=... EditingDomain ed=... Command cmd=RemoveCommand.create(ed,d); ed.getCommandStack().execute(cmd);

注:这里使用了RemoveCommand的静态方法create,而不是new一个RemoveCommand对象,
而且传递的参数也只有要删除的对象(department),而不像之前还要包括所删除对象的父对象(company),那么该父对象是怎样得到的呢?

create静态方法如下:
public static Command create(EditingDomain domain, Object value) { return domain.createCommand( RemoveCommand.class, new CommandParameter(null, null, Collections.singleton(value))); }

可以看到,方法调用了EditingDomain的createCommand方法,然后AdapterFactoryEdintingDomain(EdintingDomain的实现类)
将命令的创建转接给适配器类,让适配器类处理命令的创建过程。

createCommand方法大致如下:
public Command createCommand(Class commandClass, CommandParameter commandParameter) { Object owner = ... // get the owner object for the command IEditingDomainItemProvider adapter = (IEditingDomainItemProvider) adapterFactory.adapt(owner, IEditingDomainItemProvider.class); return adapter.createCommand(owner, this, commandClass, commandParameter); }

真的代码逻辑复杂的多,方法中省略了owner对象的获取步骤,然而owner对象是如何得到的呢?
从上面的create方法来看,在构造CommandParamter对象时,将要删除的对象以构造参数的形式传递过去(Collections.singleton(value)),
然后再将commandParameter作为参数传递到createCommand方法中,这样在createCommand方法中我们便可得到要删除的value对象,
而通过value对象的eContainer()方法,便可以获取对象的容器,即父对象owner。
方法随后调用了adapterFactory的adapt方法,来获取该父对象的适配器类,最后将业务转交给该适配器类进行处理。

适配器类会根据commandClass的值来选择与之相对应的命令执行构建操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值