用于在绘制应用程序中撤消/重做的命令模式



我想在一个小型绘画应用程序中实现undo/redo。命令模式似乎很适合使用,但我不确定如何最好地实现它

根据我对模式的理解,有必要在每个命令中包括:

  1. 用于重做的绘制操作的详细信息(例如,线->起点和终点,自由形式线-<GeneralPath)
  2. 零部件在进行撤消更改之前的状态。在这种情况下,这将是受命令影响区域的小快照图像

基于此,我的理解是,每个命令都需要是"原子的"或自包含的,以及撤消/重做该操作所需的所有信息。

不幸的是,这将需要存储比我最初预期的更多的信息。对于一条线,我们还必须考虑最初用于绘制它的ColorStrokeRenderingHints。这把我的"简单的小命令"变成了一些东西。。内存更大,需要大量生成锅炉板代码(每个代码都是一个可串行化的bean1)。

出于保存内存的原因(主要是),我想在命令的规范上"作弊"。也许每100次更新就备份整个绘图区域,但不存储更改后的图像的任何部分,只需为每次新的绘制操作重新生成最后(最多)100个命令。但是,要确保Graphics对象的状态在绘制每个零件之前是正确的,这似乎是有问题的——这个零件可能需要一条线,但RenderingHints在4个命令前被更改,Color在98个命令前更改,而Stroke在最后227个命令中保持不变。

追求内存效率更高的命令似乎把模式从"原子"的角度抛到了九霄云外。这反过来又导致难以确定可能影响渲染的最早命令。

我应该:

  • 寻找新模式
  • 尝试通过调整模式来实现我的特殊需求
  • 将所有这些作为过早的优化扔进垃圾桶,并以最简单(也是最消耗内存)的方式对其进行编码,以坚持定义的命令模式

更新

  1. "每个都将是可串行化的bean"可串行化的,但是不存储笔划的厚度。我可以创建许多属性的可序列化版本,但这似乎会产生更多的代码,所以我也将放弃该规范。我将只尝试在运行时存储对BufferedImage的引用

我会坚持使用命令模式,首先尝试一个简单的解决方案(=最需要内存的解决方案)。对于某些图形操作,甚至可能需要在命令对象中保留整个图像的副本(例如,考虑过滤器)。这也是专业图像编辑应用程序中的一个常见问题,它们通常对记住的最后命令有内存或步长限制。如果内存消耗非常大,您可能会考虑将命令历史记录中最旧的条目交换到文件系统。我认为用户不会介意等待一秒钟,直到更改被撤销。

也许,最好不要在命令中存储整个图像的副本,而只存储区域的副本,这会随着命令的变化而变化。当然,这不是万能的

最新更新