(注:大部分翻译,整理自
Eclipse Modeling Framework: A Developer's Guide
一书的第
3.3, 3.4
节的内容)
EMF
的
Command
框架分为两个部分,
Common Command Framework
和
EMF.Edit
的
Commands
。
Common Command Framework
定义了基本的
Command
接口并提供了一些基本的类,例如
CommandStack, CompoundCommand
等。这个
Command
框架是非常通用的,并不依赖于
EMF.Edit
,甚至也不依赖于
EMF
,是完全独立的一个框架。而
EMF.Edit
的
Commands
,则是专门用来编辑
EObjects
的。
Command
接口是所有
Command
必须实现的基本接口。包括了
execute()
,
undo(), redo()
等方法。
Command
在执行先会先进行测试,执行
canExecute()
判断其能否被执行。
canUndo()
被用来检查一个
Command
是否能被
undo()
,它返回
false
也就意味着
redo()
和
undo()
没有被实现。
Command
接口的
getResult()
和
getAffectedObjects()
方法是可选的,但是有时候非常有用。
getResult()
可以用来返回一个执行的结果对象,而
getAffertedObjects()
方法则可以用来返回在执行的过程中被修改过的对象。通常
getAffertedObjects()
可以和
getResult
返回相同的对象,但也并不总是如此。
AbstractCommand
提供对
Command
接口的缺省实现。唯一重要的实现是
canExecute()
方法,将控制流转交给另一个钩子方法
prepare()
。然而
prepare()
只被执行一次,而不论
canExecute()
被执行多少次,这个特性在某些情况下可以避免大量的计算被重复执行。
public boolean canExecute() {
if (!isPrepared) {
isExecutable = prepare();
isPrepared = true;
}
return isExecutable;
}
CommandStack
接口定义了一个
Command
栈,使用后进先出的方式保存所有执行过的
Command
,使得
undo()
和
redo()
能够被方便的实现。
BasicCommandStack
是
CommandStack
接口的一个简单实现。
CompoundCommand
是一个很有用的类。可以让你通过基本的
Command
对象来组合更为复杂的高层次的
Command
。它的
execute()
方法会依次调用每一个成员
Command
;而
canExecute()
等测试方法在当所有成员
Command
的
canExecute()
方法返回为
true
是方返回
true
。一个有用的技巧是使用
appendAndExecute()
来加入并立即执行一个
Command
;使用这个方法可以记录一个命令执行的序列,并一次性的进行
undo()
。
EMF.Edit Commands
在
Common Command Framework
的基础上,执行专门正对于
EObject
的命令。它定义了如下的几个基本
Command
:
1.
SetCommand
:用来为
EObject
的
attribute
或者
reference
设置值。
2.
AddCommand
:用来为
EObject
的
multiplicity
为
many
的
feature
添加一个或者多个值。
3.
RemoveCommand
:则是用来做和
AddCommand
相反的事情。
4.
MoveCommand
:用来移动对象在
multiplicity
为
many
的
feature
中的位置。
5.
ReplaceCommand
:用来替换一个
multiplicity
为
many
的
feature
中的对象。
6.
CopyCommand
:执行
EObject
对象的深度拷贝(
Clone
)
.
除了
CopyCommand
之外,其他的
Command
均为简单命令,而
CopyCommand
命令则是由
CreateCopyCommand
和
InitializeCopyCommand
这两个命令组合而成。
除了上述的基本命令之外,
EMF.Edit
基于基本命令的,执行
High Level
编辑功能的命令:
1.
CreateChildCommand
。
2.
CutToClipboardCommand
。
3.
CopyToClipboardCommand
。
4.
PasteFromClipboardCommand
。
5.
DragAndDropCommand
。
AbstractOverrideableCommand
作为
EMF.Edit
的
Command
的抽象基类,上面大部分的命令均继承于它,而
AbstractOverrideableCommand
则是继承于
AbstractCommand
。它提供了扩展机制来覆盖其自生的
execute()
方法:
public final void execute() {
if (overrideCommand != null)
overrideCommand.execute();
else
doExecute();
}
之所以这样做的,而不是直接使用继承来扩展
Command
原因,是因为你可以使用
Common Command
来实现模型相关而与
EMF
无关的
Command
,来扩展这些专门针对于
EMF EObjects
的命令。从上面的代码也可以看出,如果要用继承来覆盖已有的命令的话,应该覆盖
doExecute()
方法而不是
execute()
方法。
通常,
Command
都是由
EditingDomain
接口的
createCommand(Class commandClass, CommandParameter commandParameter)
来创建的,它接受通用的
CommandParater
参数,来创建
Command
。但是,为了方便起见,每一个
EMF.Edit Command
都提供了
static
的
create()
方法来创建相应的对象,而由它在来调用
EditingDomain
的
createCommand()
。
EditingDomain
需要完成三种功能:
1.
创建
commands
,在
AdapterFactoryEditingDomain
中这是通过代理到一个
Item Provider
来实现的。
2.
管理
Command Undo
栈,通过
CommandStack
来实现。
3.
提供方法来访问
EMF
模型对象的
ResourceSet
,以及
load
或者
save Resource
。
创建一个对象,一般来说使用的是
Command
的静态
create()
方法。例如对于
RemoveCommand
来说,可以通过如下的代码来创建一个
RemoveCommand
:
Command cmd = RemoveCommand.create(editingDomain,
aPurchaseOrder,
poPackage.getPurchaseOrder_Items(),
aItem);
在
EditingDomain
的
ResourceSet
之间存在有双向的关联。因为一个对象知道其
Resource
,而
Resource
又知道其
ResourceSet
,因此,由一个对象可以得到其
EditingDomain
,而
EditingDomain
又提供了创建
Command
的方法,因此一个对象可以在任何地方都能够创建修改这个对象的
Command
了,如下例所示:
EditingDomain editingDomain = getEditingDomain(object);
editingDomain.getCommandStack().execute(
SetCommand.create(editingDomain, object, feature, value));
posted on 2006-05-26 21:11
llh 阅读(279)
评论(0) 编辑 收藏 所属分类:
EMF