eclipshine

          Eclipse主題站

          EMF.Edit編程學習筆記之二: Command框架

          (注:大部分翻譯,整理自Eclipse Modeling Framework: A Developer's Guide一書的第3.3, 3.4節的內容)

          EMF
          Command框架分為兩個部分,Common Command FrameworkEMF.EditCommands。Common 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 閱讀(1926) 評論(0)  編輯  收藏 所屬分類: EMF

          主站蜘蛛池模板: 河池市| 常熟市| 将乐县| 金昌市| 日照市| 贵德县| 安远县| 拜城县| 文化| 澄城县| 乐山市| 梨树县| SHOW| 来宾市| 桦甸市| 尼玛县| 吴江市| 公安县| 通渭县| 北海市| 古浪县| 内黄县| 綦江县| 乌什县| 怀远县| 信丰县| 赫章县| 吴堡县| 太原市| 吉安市| 建宁县| 邛崃市| 田林县| 广州市| 湖南省| 科尔| 宝兴县| 遂昌县| 蛟河市| 余庆县| 依安县|