快捷搜索:

C#中使用命令模式实现Undo/Redo

  【IT168 专稿】

  关于Undo/Redo实现的基本思想

  正如我们所知,应用程序在每次操作后改变其状态。当操作应用程序时,它的状态会发生改变。所以,若有人想要做撤销,他不得不回到先前的状态。因此,为了能够回到先前状态,我们需要在应用程序运行时存储它的状态。要支持重做,我们不得不从目前状态跳到下一个状态。

  第一篇:C#中使用单个对象的方法实现Undo/Redo

为了实现Undo/Redo,我们不得不存储应用程序的状态并在撤销时跳到前一个状态而在重做时跳到下一个状态。因此我们需要维护应用程序的状态来支持Undo/Redo。在所有三种方法中,应用程序状态的维护用到了两个栈。一个栈包含用于撤销操作的状态,第二个包含用于重做的状态。撤销操作弹出撤销栈以获取前一个状态并将其设置给应用程序。同样的,重做操作弹出重做栈以获取下一个状态并将其设置给应用程序。

现在,我们知道了Undo/Redo的实现操作都是关于保持应用程序每次操作后的状态。现在的问题是该方法如何保存状态。在命令模式中,我们将单个操作的变化保存在一个ICommand对象中,它的目的在于把这种特殊类型的操作看作状态。

关于命令模式

这里我并不打算讨论命令模式,你可从这和这了解该模式相关信息。

如何应用命令模式对任意应用程序Undo/Redo操作建模?

命令模式如何对任意应用程序Undo/Redo操作建模将在以下步骤中讨论:

步骤1

首先识别出你希望哪些操作能支持Undo/Redo,并识别出操作将要应用的那些对象以及Undo/Redo操作的容器。

步骤2

对每个识别出的操作,使命令类继承自ICommand。每个命令类将包含它所代表的操作进行Undo/Redo时所需的属性。ICommand接口如下:

interface ICommand
    {
        
void Execute();
        
void UnExecute();
    }

在Execute()方法中,你将利用命令的属性来完成动作。在Unexecuted ()方法中,你将利用命令的属性完成撤销操作。这里命令的属性保存它对应的命令完成Undo/Redo需要的变化,以及它改变的那些对象的引用。

特别注意:如果同一个操作对不同对象表现不同的行为,那么你不得不为此操作准备多重命令。这是针对每个对象类型的操作命令。
  步骤3

然后创建一个名为UndoRedo的类,它包含两个栈。第一个用于Undo操作,第二个用于Redo操作。该类实现Undo方法,Redo方法和许多的InsertInUnDoRedo方法以在Undo / Redo系统中插入ICommand对象。当InsertInUnDoRedo方法被调用,然后ICommand对象被插入Undo栈,使Undo / Redo操作可用并清除Redostack。

在Undo操作中:
•首先检查UndoStack是否为空。如果为空则返回否则继续。
•然后从UndoStack中弹出一个ICommand对象。
•再次把该命令压入RedoStack。
•最后调用Icommand对象的Unexecute方法。

在Redo操作中:
  •首先检查RedoStack是否为空。若为空则返回,否则继续。
  •然后从RedoStack中弹出一个Icommand对象。
  •再次把该命令压入Undostack。
  •最后调用Icommand对象的execute方法。

步骤4

当你执行应用程序内不同的操作时,创建该操作类型的Command对象并通过名为InsertInUnDoRedo的方法将其压入Undo/Redo系统。当你需要做Undo操作时,只要调用应用程序中UndoRedo类的Undo方法,而当你想做Redo操作时,你只要调用应用程序的redo操作。

您可能还会对下面的文章感兴趣: