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 閱讀(1932) 評論(0)  編輯  收藏 所屬分類: EMF

          主站蜘蛛池模板: 合肥市| 阿尔山市| 华安县| 抚顺市| 鄱阳县| 太仓市| 个旧市| 北辰区| 永嘉县| 错那县| 望都县| 奉化市| 虞城县| 江油市| 从化市| 雷州市| 临沭县| 绥阳县| 若尔盖县| 丹东市| 新竹市| 荔波县| 连城县| 额济纳旗| 洛川县| 丹寨县| 寿宁县| 林芝县| 崇明县| 双流县| 慈溪市| 武鸣县| 阿图什市| 开化县| 平罗县| 微山县| 韶关市| 都匀市| 尼木县| 体育| 元江|