试图实现Undo / Redo,发现这篇文章我不太明白。救命?

时间:2011-08-09 13:38:24

标签: c# command design-patterns undo-redo

在我的应用程序中,有一个多维数组,可能包含大量数据,因此每次用户更改时都会完全保存该对象,这似乎是不可行的。

我阅读了有关Command模式的文章并最终找到了this文章,但我不太明白。我不确定他的代码示例是如何工作的,以及这是否适用于我的应用程序。此外,这种“新”方法是否优于GoF模式?

我的应用程序有一些工具,如刷子和填充工具,可用于当前文档,我不确定如何最好地实现撤消/重做功能,但我知道保存对象的状态,因为每个操作都不允许无限的撤销和重做,这就是我所追求的。我不确定是否可以在此上下文中使用Command模式,或者是否以及文章的实现是如何工作的。

希望有人可以详细说明这篇文章或解释Command模式如何适应我的需求。谢谢你的阅读!

2 个答案:

答案 0 :(得分:1)

创建一个具有三个值的类(location,oldvalue和newvalue,其中location指向多维数组中的元素)和两个方法(undo,redo)。在每个操作上,为大型数组中的每个元素创建一个这些对象的数组,并将其推送到撤消堆栈。弹出撤消堆栈时,调用undo,然后按下重做堆栈。与重做流行相反。记得用新动作清除重做堆栈。

修改

样品:

public void undo()
{
    location = oldvalue;
}

public void redo()
{
    location = newvalue;
}

然后是一个堆栈的例子:

command = undoStack.Pop();
command.undo();
redoStack.Push(command);

答案 1 :(得分:1)

只是做了一些研究,我就找到了一些可能的解决方案。最简单的可能是使用堆栈。另一种是使用纪念图案。但是你问自己这里的命令模式是一个简单的例子。

这主要取自codeprojects示例。

class Document
{
   private List<string> _textArray = new List<string>();

   public void Write(string text)
   {
       _textArray.Add(text);
   }
   public void Erase(string text)
   {
       _textArray.Remove(text);
   }
   public void Erase(int textLevel)
   {
       _textArray.RemoveAt(textLevel);
   }

   public string ReadDocument()
   {
       System.Text.StringBuilder sb = new System.Text.StringBuilder();
       foreach(string text in _textArray)
           sb.Append(text);
       return sb.ToString();
   }
}

abstract class Command
{        
   abstract public void Redo();
   abstract public void Undo();
}

class DocumentEditCommand : Command
{
   private Document _editableDoc;
   private string _text;

   public DocumentEditCommand(Document doc, string text)
   {
       _editableDoc = doc;
       _text = text;
       _editableDoc.Write(_text);
    }
   override public void Redo()
   {
       _editableDoc.Write(_text);
   } 
   override public void Undo()
   {
       _editableDoc.Erase(_text);
   }
}

class DocumentInvoker
{
   private List<Command> _commands = new List<Command>();

   private Document _doc = new Document();

   public void Redo( int level )
   {
       Console.WriteLine( "---- Redo {0} level ", level );
       ((Command)_commands[ level ]).Redo();
   }

   public void Undo( int level )
   {
       Console.WriteLine( "---- Undo {0} level ", level );
       ((Command)_commands[ level ]).Undo();
   }

   public void Write(string text)
   {
       DocumentEditCommand cmd = new 
       DocumentEditCommand(_doc,text);
       _commands.Add(cmd);
   }

   public string Read()
   {
      return _doc.ReadDocument();
   }
}

使用命令模式。

我们对documentinvoker的实例做了两个“动作”(实现我们的命令模式)。

DocumentInvoker instance = new DocumentInvoker ();
instance.Write("This is the original text.");
instance.Write(" Here is some other text.");

现在我们可以撤消这些行动。

instance.Undo(1);

现在文件中的文字将是。

---- Undo 1 level
This is the original text.

现在我们可以重做这个动作

instance.Redo(1);

文字将是。

---- Redo 1 level
This is the original text. Here is some other text.

显然,你需要修改它以满足你的需求。如果您想要更多解释,请查看文章http://www.codeproject.com/KB/books/DesignPatterns.aspx