使用Memento撤消/重做:堆栈,队列还是仅链接列表?

时间:2010-02-25 10:58:20

标签: .net design-patterns collections

实施Memento pattern(用于撤消/重做)

时最佳用途

收集Keep Mementos的女巫系列?

基本上,我需要这个(c = change,u = undo,r = redo):

                  0
                  *c
            -1    0
                  *c
      -2    -1    0
                  *c
-3    -2    -1    0
                  <u
      -2    -1    0    1
                  *c
-3    -2    -1    0

变种:

  • LinkedList - 原则上可能,可能没有优化。
  • 队列 - 不适合此任务,IMO。
  • 堆叠 - 不适用于撤消AND重做;
  • 双重叠加 - 可能是最佳的,但无法控制撤消最大尺寸。

5 个答案:

答案 0 :(得分:1)

最后,我使用了LinkedList

Public Sub Add(ByVal item As T)
  If _list.Count > 0 Then
    If Me.IsFull Then
      ' we forgot (delete) the oldest state '
      _list.RemoveFirst()
    End If
    ' remove all the following the current items objects '
    Dim lastNode As LinkedListNode(Of T) = _list.Last
    While Not Object.ReferenceEquals(_currentNode, lastNode)
      _list.RemoveLast()
      lastNode = _list.Last
    End While
  End If

  ' add the new item and point current to it '
  _currentNode = _list.AddLast(item)
End Sub

答案 1 :(得分:0)

撤消时,您将要恢复到最近覆盖的数据。因此,您想要使用的纪念品将是添加到该系列中的最后一个纪念品。由于堆栈是先进先出(LIFO),因此它们应该是您的意图的理想选择。

注意:您可能希望查看命令模式,因为它对实现撤消功能非常有用。

编辑:没注意到你想要重做。从你的堆栈弹出的东西将摆脱它,这样对你的目的没有多大用处。链接列表应该有效。

答案 2 :(得分:0)

您是否希望用户能够选择多个项目进行撤消或重做?

如果是这种情况,那么您可能希望使用通用List或ObservableCollection(如果是WPF / Silverlight),以便可以在UI中显示这些项。您可以使用两个列表:一个用于撤消,一个用于重做。

答案 3 :(得分:0)

使用双向链表。当用户使用撤销/重做时,他们可以多次索引状态(例如,做4个撤消,然后意识到他们走得太远并做重做)。单个堆栈或队列不支持该功能。

两个堆栈将支持撤销和重做,但我认为使用它们是一种浪费。一旦用户执行编辑(创建新的纪念品),所有重做纪念品将最终被删除。因此,大多数情况下,应用程序运行时将没有“重做”纪念品。

假设您已将垃圾收集标记为.net: 当用户进行编辑时,您将要对双向链接列表进行所有操作,将链接列表的头部引用设置为当前的纪念品。如果您使用堆栈,那么您将不得不创建一个新堆栈或弹出所有内容,以便gc释放重做纪念品。

答案 4 :(得分:0)

双头队列优选用于有效地支持撤消重做操作。当用户键入单词时,节点将插入到队列中,并且头指针指向当前位置。触发撤消操作时,只需将磁头移到上一个节点,然后在重做操作中将磁头指针移到列表中的下一个位置。如果进行编辑操作,请删除头右边的所有节点,并在头末端插入。这样,我们可以在 O(1)时间复杂度中执行撤消重做。