【问题标题】:Fast undo/redo with memento/command pattern?使用备忘录/命令模式快速撤消/重做?
【发布时间】:2011-03-16 01:45:38
【问题描述】:

我正在为手机编写绘画/图形 Java 应用程序(因此内存有限)。应用程序状态本质上是三个 1000x500 位图(即绘画的图层)。加载三个位图大约需要 2 或 3 秒。

我正在尝试编写一个撤消引擎,但我无法找到一个好的方法来做到这一点。典型的做法是:

  • 使用命令模式:撤消时,会重新加载初始文件的状态,然后播放到目前为止处理的所有命令,最后一个命令除外。天真地这样做意味着等待 2 或 3 秒来加载太慢的初始状态。内存中也没有足够的内存来存储初始状态。

  • 使用备忘录模式:撤消时,会将当前状态中已更改的部分替换为旧状态。这意味着每个操作都需要将旧状态的位图保存到磁盘,因为移动设备上没有足够的内存来将其存储在内存中。由于保存位图需要时间,如果用户决定例如,我该如何应对?快速连续绘制许多笔触?我不能让他们等。

我所有的解决方案都涉及上述模式的复杂混合。

任何人都可以提出一个解决方案,让我可以对我的应用程序进行相当快速的撤消/重做吗?

【问题讨论】:

标签: java android design-patterns oop optimization


【解决方案1】:

还有第三种常用的处理撤销的方法。即在 Undo 对象中存储两种状态之间的差异。您可以将其视为实际差异(即哪些像素已更改以及它们更改为什么),但这可能几乎与在每个阶段存储位图一样浪费内存。

另外,您可以使用命令模式方法,但不是在撤消时重新运行命令,而是存储命令的反转 - 即如果用户将红色值增加 10,则撤消命令将减少十点。要撤消您只需执行反向命令。有些命令很难找到相反的命令,例如“转换为黑白”,但是通过将底层位图与许多通过命令打开或关闭的过滤器混合,您可能可以做到。

作为另一个建议,使用您提到的命令方法,但为上一步保留位图。当用户撤消时,立即显示上一步 (n-1) 的缓存位图,然后开始计算 n-2 的位图,以便在他再次按下撤消时做好准备。

【讨论】:

  • 还有一些不可撤销的命令也是完全可以接受的,比如“转换成黑白”,只要在用户执行之前提示用户是这样的。跨度>
  • @StrixVaria:我想到了这一点,但宁愿避免这种情况,因为这不是用户在绘画应用程序中所期望的。我认为好的 iphone 应用程序有不错的撤销。
  • 谢谢。存储差异似乎是对纪念品模式的优化。我的主要行动是 1)在这些地方绘制 50 个蓝色油漆斑点 2)将饱和度更改为 20%;正如您所说,存储差异或编写逆向操作在这里无济于事。我喜欢你最后的建议。这个想法的一个变种是,当用户绘图时,机器通过缓存撤消位图的命令列表工作。不过,我需要考虑一下 CPU 和电池使用问题。
【解决方案2】:

关于你的使用命令模式要点:从初始状态开始,再次执行命令根本不需要。如果要支持撤消操作,每个 Command 类应该代表一个小的用户操作,并且应该有机制来撤消它在其 execute() 方法中所做的事情。我们维护一堆 ***Command 对象。当用户撤消某项操作时,会从堆栈中弹出一个 Command 对象并调用其 undo() 方法。

在您的情况下,我没有看到使用备忘录模式的任何动机,因为撤消操作将按 FIFO 顺序进行。我猜,不允许用户随意撤消操作。

【讨论】:

    猜你喜欢
    • 2017-06-28
    • 2013-12-20
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 2015-06-22
    • 2011-06-14
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多