eclipshine

Eclipse主题站

EMF.Edit编程学习笔记之二: Command框架

(注:大部分翻译,整理自Eclipse Modeling Framework: A Developer's Guide一书的第3.3, 3.4节的内容)

EMF
Command框架分为两个部分,Common Command FrameworkEMF.EditCommandsCommon Command Framework定义了基本的Command接口并提供了一些基本的类,例如CommandStack, CompoundCommand等。这个Command框架是非常通用的,并不依赖于EMF.Edit,甚至也不依赖于EMF,是完全独立的一个框架。而EMF.EditCommands,则是专门用来编辑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()能够被方便的实现。BasicCommandStackCommandStack接口的一个简单实现。

 

CompoundCommand是一个很有用的类。可以让你通过基本的Command对象来组合更为复杂的高层次的Command。它的execute()方法会依次调用每一个成员Command;而canExecute()等测试方法在当所有成员CommandcanExecute()方法返回为true是方返回true。一个有用的技巧是使用appendAndExecute()来加入并立即执行一个Command;使用这个方法可以记录一个命令执行的序列,并一次性的进行undo()

 

EMF.Edit CommandsCommon Command Framework的基础上,执行专门正对于EObject的命令。它定义了如下的几个基本Command

1.       SetCommand:用来为EObjectattribute或者reference设置值。

2.       AddCommand:用来为EObjectmultiplicitymanyfeature添加一个或者多个值。

3.       RemoveCommand:则是用来做和AddCommand相反的事情。

4.       MoveCommand:用来移动对象在multiplicitymanyfeature中的位置。

5.       ReplaceCommand:用来替换一个multiplicitymanyfeature中的对象。

6.       CopyCommand:执行EObject对象的深度拷贝(Clone.

除了CopyCommand之外,其他的Command均为简单命令,而CopyCommand命令则是由CreateCopyCommandInitializeCopyCommand这两个命令组合而成。

 

除了上述的基本命令之外,EMF.Edit基于基本命令的,执行High Level编辑功能的命令:

1.       CreateChildCommand

2.       CutToClipboardCommand

3.       CopyToClipboardCommand

4.       PasteFromClipboardCommand

5.       DragAndDropCommand

 

AbstractOverrideableCommand作为EMF.EditCommand的抽象基类,上面大部分的命令均继承于它,而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都提供了staticcreate()方法来创建相应的对象,而由它在来调用EditingDomaincreateCommand()

 

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

 

EditingDomainResourceSet之间存在有双向的关联。因为一个对象知道其Resource,而Resource又知道其ResourceSet,因此,由一个对象可以得到其EditingDomain,而EditingDomain又提供了创建Command的方法,因此一个对象可以在任何地方都能够创建修改这个对象的Command了,如下例所示:

EditingDomain editingDomain = getEditingDomain(object);

editingDomain.getCommandStack().execute(

  SetCommand.create(editingDomain, object, feature, value));

 

posted on 2005-07-29 23:33 Living Not Striving 阅读(1900) 评论(0)  编辑  收藏 所属分类: EMF


只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问