实现撤消/重做

时间:2014-03-24 17:07:43

标签: c# .net performance undo-redo

在绘图应用程序中,我使用Memento pattern实现多级撤消/重做。我面临的一个问题是,如果图形包含一个或多个图像对象,则纪念品(状态对象)会变得太大(我的绘图对象可以嵌入base64编码的图像对象,就像Visual Studio' s resx文件),由于绘图应用程序中常见的频繁鼠标操作,这将使撤消/重做堆栈很快爬升到几兆字节。为了解决这个问题,我在其中引入了gzip压缩,以便我现在将一个压缩版本的纪念品保存到堆栈中。这导致整体堆栈大小减少约90%。

现在这导致了另一个问题。压缩/解压缩纪念品所花费的时间在对象定位/调整大小方面引入了相当多的麻烦。

解决此问题的一种方法是使用Command pattern,但我不愿意走这条路,因为它会在应用程序的许多部分引入大量工作。你还看到了其他的替代品吗?

2 个答案:

答案 0 :(得分:2)

我能想到的唯一解决方案是在不完全切换到Command模式的情况下,生成一种incremental backup对象作为纪念品,而不是使用整个对象。

我们的想法是,您可以从纪念品中删除任何尚未改变的数据。然后你只会存储差异。

进行撤消时,您将使用对象的当前状态和差异生成纪念品并在此过程中将其注入。

这里基本上是这样的:

  1. 看护人会对发起人做些什么,但希望能够撤销更改。
  2. 看护人首先要求发起人提供纪念品。
  3. 然后它会执行它要执行的任何操作(或操作序列)。
  4. 压缩器将比较发起人的纪念品和新状态,并生成将存储在操作堆栈上的差异对象
  5. 撤消:

    1. 压缩器将从创建者状态和差异对象重新创建纪念品对象
    2. 然后使用新纪念品恢复发起人状态。
    3. 压缩器类的实现可能很棘手,并且取决于您将要执行的操作类型。

      您将使用一个单独的memento对象并仅存储diff对象,如果需要也可以对其进行压缩,但可能会相当小。

答案 1 :(得分:1)

当我在90年代用Delphi做类似的事情时,我在堆栈/队列/列表上进行了大量绘制操作后,每当重绘速度太慢时,我都会拍摄快照,即当前状态的位图。但不确定你是否可以这样做。