【问题标题】:Memory management in undo/redo framework撤消/重做框架中的内存管理
【发布时间】:2018-09-12 08:10:16
【问题描述】:

我正在为我用 C# 开发的软件的一部分实现撤消/重做功能。发生撤消/重做操作的数据存储为对象列表List<MyClass>。在某些情况下,列表的大小可能会变大 (>1k)。

我希望用户尽可能多地撤消/重做。但是,如果我只是简单地存储所有以前的状态(如在备忘录模式中),它可能会导致软件占用过多的内存,这是我不希望的。

我想出的解决方案列表是:

  1. 将状态存储在某个文件中,一次只能读取几个状态。这样我不会占用大量 RAM,但读取和写入文件可能会很耗时(可能必须在另一个线程上运行)。
  2. 计算两个连续状态之间的增量并将其存储起来。例如,UNDO: DEL LIST[5] & REDO: INSERT <object> LIST[5]

还有哪些其他有效的方法可以实现撤消/重做功能?它们与上述解决方案相比如何?

【问题讨论】:

  • 一个想法:不要做 List 的深拷贝。 . .相反,对于所有相等的节点,指向上一个列表中的原始对象。当然,这假设您完全注意不直接更改任何原始 MyClass 项。 . .相反,如果你想改变一个,你先复制它。 . .然后将其放入新列表并更改新对象。即使有 1K 个对象。 . .只有一两个可能会在角色后卫位置之间发生变化。
  • 根据您的要求,可以查看事件溯源/CQRS 模式

标签: c# .net undo-redo


【解决方案1】:

我的首选方法是为应用程序的不同部分使用不同的堆栈,并将它们聚合在一起。我觉得这非常有效。我发布了一个实现这种方法的开源项目 - https://www.nuget.org/packages/UndoService/

我已将这种方法与您的第一个建议结合使用。在我的应用程序中更改背景图像时,它只存储 Id,并根据需要从磁盘加载它。其他对象使用较少的内存,因此它们的整个状态只是存储在 RAM 中的堆栈中。撤消服务使用委托来访问状态和通用堆栈,因此混合这样的方法非常简单。

我之前使用了一种基于与您的第二个建议相同概念的通用方法。这是为了使用 Command 模式和在 Command 接口中定义的 Undo() 方法。就执行期间的资源而言,这是一种非常有效的方法,因为它根本不需要存储状态,只需要存储命令。然而,我放弃了它,转而使用 Memento,因为它涉及额外的开发时间和复杂性。也就是说,它非常适合某些项目,尤其是在命令数量不太多或应用程序状态的内存印记很重要的情况下。

【讨论】:

    猜你喜欢
    • 2011-12-03
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多