尝试实现撤消/重做,发现这篇文章我不太明白。帮助?

发布于 2024-11-28 19:27:43 字数 434 浏览 6 评论 0原文

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

我阅读了有关命令模式的内容,最终找到了这个 文章,但我不太明白。我不确定他的代码示例如何工作以及这是否适用于我的应用程序。另外,这种“新”方法比 GoF 模式更好吗?

我的应用程序具有适用于当前文档的画笔和填充工具等工具,我不太确定如何最好地实现撤消/重做功能,但我知道为每个操作保存对象的状态将不允许无限撤消和重做这就是我所追求的。我不确定命令模式是否可以在这种情况下使用,或者本文的实现是否以及如何工作。

希望有人可以详细说明这篇文章,或者解释一下命令模式如何适应我的需求。感谢您的阅读!

In my application there is a multidimensional array with potentially a lot of data so completely saving that object every time the user changes it seems unfeasible.

I read about the Command pattern and eventually found this article but I do not quite understand it. I'm not sure about how his code example works and whether or not this will work in my application. Also, is this "new" method preferable to the GoF pattern?

My application has tools like a brush and fill tool that work on the current document and I'm not really sure how to best implement undo/redo functionality but I know saving the state of the object for every operation would not allow for infinite undo's and redo's which is what I'm after. I'm not sure if the Command pattern can be used in this context or whether or not and how the article's implementation works.

Hopefully someone can elaborate upon the article or perhaps explain how the Command pattern could be adapted to my needs. Thanks for reading!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陌上青苔 2024-12-05 19:27:43

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

编辑:

示例:

public void undo()
{
    location = oldvalue;
}

public void redo()
{
    location = newvalue;
}

然后是堆栈的示例:

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

Create a class with three values (location, oldvalue, and newvalue, where location points to an element in your multidimensional array) and two methods (undo, redo). The on each operation, creat an array of these object for each element in your large array that changes, and push it onto an undo stack. When popping off the undo stack, call undo, and then push to a redo stack. Opposite for redo pop. Just remember to clear the redo stack with new actions.

EDIT:

Sample:

public void undo()
{
    location = oldvalue;
}

public void redo()
{
    location = newvalue;
}

And then an example of the stacks:

command = undoStack.Pop();
command.undo();
redoStack.Push(command);
月棠 2024-12-05 19:27:43

只需做一点研究就可以让我找到一些可能的解决方案。最简单的可能是使用堆栈。另一种是使用纪念品模式。但是既然您询问了命令模式,这里就是一个简单的例子。

这基本上取自 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

Just doing a little research lead me to a few possible solutions. Simplest is probably using a stack. Another is using the memento pattern. But you since you asked about the command pattern here is a simple example.

This is essentially taken from codeprojects example.

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

Using the command pattern.

We do two "actions" to the instance of the documentinvoker (implementing our command pattern).

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

now we can undo those actions.

instance.Undo(1);

The text in the document will now be.

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

now we can redo this action

instance.Redo(1);

The text will be.

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

Obviously you'll need to modify this to meet your needs. And if you want a little more explanation check out the article http://www.codeproject.com/KB/books/DesignPatterns.aspx.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文