为了账号安全,请及时绑定邮箱和手机立即绑定

撤消引擎的设计模式

撤消引擎的设计模式

开心每一天1111 2019-12-09 10:20:44
我正在为民用工程应用程序编写结构建模工具。我有一个代表整个建筑物的巨大模型类,其中包括节点,线元素,荷载等的集合,它们也是自定义类。我已经编码了一个撤消引擎,该引擎在对模型进行每次修改后都保存了一个深拷贝。现在,我开始考虑是否可以使用其他代码进行编码。除了保存深层副本之外,我还可以保存每个修改器动作的列表以及相应的反向修改器。这样我就可以将反向修改器应用于当前模型以撤消,或将修改器应用于重做。我可以想象您将如何执行更改对象属性等的简单命令。但是复杂命令呢?就像将新的节点对象插入模型并添加一些线对象以保留对新节点的引用一样。如何实施呢?
查看完整描述

3 回答

?
MMTTMM

TA贡献1869条经验 获得超4个赞

我见过的大多数示例为此使用了Command-Pattern的变体。每个无法撤消的用户操作都会获取其自己的命令实例,该实例包含所有信息以执行该操作并将其回滚。然后,您可以维护所有已执行命令的列表,然后可以将它们逐一回滚。


查看完整回答
反对 回复 2019-12-09
?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

我认为在处理OP所暗示的规模和范围模型时,纪念品和命令都不实用。它们会起作用,但是维护和扩展将需要大量工作。

对于此类问题,我认为您需要建立对数据模型的支持,以支持模型中涉及的每个对象的差异检查点。我曾经做过一次,而且效果很好。您要做的最大事情是避免在模型中直接使用指针或引用。

每个对另一个对象的引用都使用一些标识符(例如整数)。只要需要该对象,就可以从表中查找该对象的当前定义。该表包含每个对象的链接列表,每个对象都包含所有以前的版本,以及有关它们针对哪个检查点处于活动状态的信息。

撤消/重做的实现很简单:执行您的操作并建立一个新的检查点;将所有对象版本回滚到先前的检查点。

它在代码中需要一定的纪律,但是却具有许多优点:因为您正在对模型状态进行差异存储,所以您不需要深层副本。您可以根据重做次数或使用的内存来确定要使用的内存量(对于CAD模型之类的数据非常重要);模型上运行的功能具有高度的可扩展性和低维护性,因为它们无需执行任何操作即可实现撤消/重做。


查看完整回答
反对 回复 2019-12-09
?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

正如其他人所述,命令模式是实现撤消/重做的一种非常强大的方法。但是我想提及命令模式有一个重要的优势。

使用命令模式实现撤消/重做时,可以通过抽象化(在某种程度上)对数据执行的操作并在撤消/重做系统中利用这些操作来避免大量重复的代码。例如,在文本编辑器中,剪切和粘贴是互补的命令(除了剪贴板的管理之外)。换句话说,剪切的撤消操作是粘贴,剪切的撤消操作被剪切。这适用于更简单的操作,例如键入和删除文本。

关键是可以将撤消/重做系统用作编辑器的主要命令系统。无需编写“创建撤消对象,修改文档”之类的系统,而是可以“创建撤消对象,对撤消对象执行重做操作以修改文档”。

现在,诚然,许多人都在想:“好吧,这不是命令模式的重点吗?” 是的,但是我看到太多的命令系统具有两组命令,一组用于立即操作,另一组用于撤消/重做。我并不是说不会有特定于立即操作和撤消/重做的命令,但是减少重复将使代码更具可维护性。


查看完整回答
反对 回复 2019-12-09
  • 3 回答
  • 0 关注
  • 489 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信