我正在编写一个位图编辑器,我使用命令模式来表示将转换文档的操作。我将目前执行的所有命令保存在列表中,为了实现撤消,我将文档恢复到其初始状态,然后重放除最后一个命令之外的所有命令。
我希望我的undo / redo系统具有以下功能:当用户关闭编辑器并返回时,文档包括可用的undo和redo命令应该恢复到状态就在用户离开的时候。
我正在为Android实现此功能,您可以在从内存中清除应用程序之前通知您的应用程序,例如,用户接到电话。另外,我的一些命令是例如用户绘制的所有x,y co-ord的列表,这些可能需要一些时间才能保存到磁盘。
我目前的想法如下:
我希望撤消限制大约是20或30个命令,所以我需要额外的逻辑来丢弃命令,删除.cmd文件,我不得不担心多线程行为。这个系统看起来相当复杂,需要进行大量测试才能确保它不会出错。
Java或Android中有什么比这更容易吗?我在哪里重新发明轮子?也许数据库会更好?
答案 0 :(得分:0)
嗯,您的代码本质上可能是必要的,其中应用程序的状态由用户的操作修改到位。这可能是快速和直接的。撤消基本上是时间旅行,如果您通过修改状态来破坏旧状态,则必须存储配方以反向重新计算它,或者存储可以重新计算它的历史记录。
就像你说的那样,你可以存储动作和初始状态并向前播放(在用户选择的历史记录的新点停止),但这意味着撤消一个动作可能导致n个动作重放。一种方法是将已保存的状态副本存储在历史列表中,以便您可以立即跳转到给定状态。为了避免使用太多的RAM /存储,如果您的系统很聪明,它可以检测历史记录中最近的(非空)保存状态并重新计算这几个stpes(假设您拥有所需的所有操作 - 这假设操作是小和状态是大(r))直到达到正确的状态。通过这种方式,您可以开始消除旧的已保存状态(删除或设置为空)(根据成本函数将状态下降到与状态回溯的时间成反比线性),对最近的过去快速撤消,以及内存/对古代历史有效的储存。我用这种方法取得了成功。
答案 1 :(得分:0)
不要回复原始版本然后执行所有操作,而应考虑使命令可逆。这样,如果您决定增加撤消历史记录的大小,则在撤消时不会引入滞后的可能性。或者,正如Jared Updike所说,您的应用程序可能会受益于近期和未来的缓存渲染结果。
我认为您使用基于文件系统的解决方案过度复杂化了。如果要维护当前工作文档的整个历史记录的备份,则应该在附加模式下保持未缓冲的日志打开,并将操作记录到它。日志应该与正在编辑的应用程序和文件的特定实例相关联,因此您不必担心另一个线程踩到您的脚趾。从该日志加载应该与从普通保存文件加载非常相似。只要在遇到撤消操作时丢弃最后读取的操作。