我正在为手机编写绘画/图形Java应用程序(因此内存有限)。应用程序状态基本上是三个1000x500位图(即绘画层)。加载三个位图大约需要2到3秒。
我正在尝试编写一个撤消引擎,但我无法找到一个好方法来做到这一点。典型的方法是:
使用命令模式:撤消时,重新加载初始文件的状态,然后播放目前为止处理的所有命令,最后一个除外。天真地这样做意味着等待2或3秒来加载太慢的初始状态。内存不足以将初始状态存储在内存中。
使用memento模式:撤消时,替换使用旧状态更改的当前状态部分。这意味着每个操作都需要将旧状态的位图保存到磁盘,因为移动设备上没有足够的内存将其存储在内存中。由于保存位图需要时间,如果用户决定例如,如何处理快速连续画多笔画笔?我无法让他们等待。
我所有的解决方案都涉及上述模式的复杂混合。
有人可以提出一个解决方案,让我能够为我的应用程序提供相当快速的撤销/重做吗?
答案 0 :(得分:9)
处理撤消的第三种常用方法。即存储Undo对象中两个状态之间的差异。您可以将此作为实际差异(即,哪些像素已更改以及更改为哪些),但这可能几乎与在每个阶段存储位图一样浪费内存。
或者您可以使用命令模式方法,但不是在撤消时重新运行命令,而是存储命令的反转 - 即如果用户将红色值增加10,则撤消命令将减少它十点。要撤消您只需执行逆命令。有些命令很难找到反转,例如“转换为黑白”,但通过混合底层位图和多个过滤器,这些过滤器可以通过命令打开或关闭,你可以这样做。
作为另一个建议,使用您提到的命令方法,但保留上一步的位图。当用户撤消时,立即显示前一个(n-1)步骤中的缓存位图,然后开始计算n-2的位图,以便在他再次按下撤消时做好准备。
答案 1 :(得分:2)
关于使用命令模式点:从初始状态开始并再次执行命令根本不需要。如果要支持撤消操作,则每个Command类应该表示一个小的用户操作,并且应该具有撤消其在execute()方法中执行的操作的机制。我们维护着一堆*** Command对象。当用户撤消某些内容时,会从堆栈中弹出一个Command对象,并调用其undo()方法。
我认为在你的情况下使用memento模式没有任何动机,因为撤消操作将按FIFO顺序排列。我想,不允许用户随意撤消操作。