【发布时间】:2011-05-01 14:47:22
【问题描述】:
我正在编写一个位图编辑器,我在其中使用命令模式来表示将转换文档的操作。我将到目前为止执行的所有命令保存在一个列表中,为了实现撤消,我将文档恢复到其初始状态,然后重播除最后一个命令之外的所有命令。
我希望我的撤消/重做系统具有以下功能:当用户关闭编辑器并返回时,文档,包括可用的撤消和重做命令,应该恢复到状态用户离开时它在里面。
我正在为 Android 实现此功能,在这种情况下,您的应用程序在从内存中清除之前几乎不会收到通知,例如:用户接到电话。另外,我的一些命令是例如用户绘制的所有 x,y 坐标的列表,因此这些可能需要一些时间才能保存到磁盘。
我目前的想法如下:
- 执行新操作时,命令对象将添加到需要保存到磁盘的命令的列表 S 中。
- 使用了一个后台线程,它将不断地从列表 S 中获取命令并将它们保存到磁盘。使用的文件名的后缀将按顺序编号。例如,如果用户填满屏幕然后画了 2 个圆圈,则命令文件可能称为 FillCommand1.cmd、DrawCircleCommand2.cmd、DrawCircleCommand3.cmd。
- 我们会定期保存一个“检查点”命令,其目的是存储完整的文档状态,这样即使 .cmd 文件之一损坏,我们也可以恢复该文档的最新版本。
- 当用户退出应用程序时,后台线程会尝试完成它可以保存的所有命令(但它可能会被杀死)。
- 在启动时,我们会查找代表可以成功加载的检查点的最新 .cmd 文件。在此之后我们可以加载的所有 .cmd 文件(即某些文件可能已损坏)进入重做命令列表,我们可以在第一个加载的检查点和我们可以加载的最旧检查点之间加载的所有 .cmd 文件进入撤消列表.
我希望撤消限制为大约 20 或 30 个命令,因此我需要额外的逻辑来丢弃命令、删除 .cmd 文件,并且我必须担心多线程行为。这个系统看起来相当复杂,需要进行大量测试以确保它不会出错。
Java 或 Android 中是否有任何东西可以帮助简化此操作?我在任何地方都在重新发明轮子吗?也许数据库会更好?
【问题讨论】:
-
“这个系统看起来相当复杂,需要进行大量测试以确保它不会出错。”欢迎来到现实世界中的应用程序。函数式编程风格可能会有所帮助(保留旧值——不能解决应用程序退出/持久性问题),但您可能会遇到内存使用问题。 “......一个数据库......”这可以帮助提高速度,但它不会从根本上使它更容易,我不相信。除非你有一个内置历史的类 git 数据库。
-
大多数位图编辑器操作都是破坏性的,所以在我看来,函数式编程风格的方法没有多大帮助。
-
对。但是,如果您的代码是返回 NewBitmap 的 Execute(Bitmap, Action) ,那么您将拥有自己的状态。当然,这会强制复制您可能不想要的位图。仅仅因为典型的方法是破坏性的,并不意味着没有其他方法(即使在大多数情况下,手工挑选的破坏性可能更好)。您选择要存储的状态的方法可能是您想要的。
-
函数式编程的另一个方面是丰富的持久数据结构集,它们共享组件,因此实际上不必显式复制状态。比较命令式方法:破坏性更新的哈希表(字典、键值存储)与更新后的映射共享数据的有限映射(实现为某种树)。再一次,它可能无法解决您特定的位图级问题,但数据结构本身是持久的或共享的(或保留自己的历史记录)的想法值得考虑,例如,由具有特定粒度的图块组成的位图。
标签: android design-patterns mobile undo