6

我在一篇文章中阅读了以下内容

不可变对象对于实现某些常见的习惯用法特别方便,例如撤消/重做和可中止事务。以撤消为例。实现撤消的一种常用技术是保留一堆对象,这些对象以某种方式知道如何反向运行每个命令(所谓的“命令模式”)。但是,弄清楚如何反向运行命令可能很棘手。一种更简单的技术是在连续命令之间维护表示系统状态的一组不可变对象。然后,要撤消命令,您只需恢复到以前的系统状态(并可能将当前状态存储在重做堆栈中)。

但是,该文章没有展示如何使用不可变对象来实现“撤消”操作的一个很好的实际示例。例如...从 gmail 收件箱中删除 10 封电子邮件。一旦你这样做,它就有一个撤消选项。不可变对象在这方面有何帮助?

4

1 回答 1

6

不可变对象将保存系统的整个状态,因此在这种情况下,您将拥有包含原始收件箱的对象 A,然后是包含已删除十封电子邮件的收件箱的对象 B,以及(实际上)一个指针从 B 回到 A 表示,如果您执行一次“撤消”,那么您将停止使用 B 作为系统的状态并开始使用 A。

但是,Gmail 收件箱太大而无法使用这种技术。您可以在实际上可以存储在相当少量内存中的文档上使用它,以便您可以保留其中的许多以进行多级撤消。

如果要保留十级撤消,则可以通过仅保留两个不可变对象(一个是当前对象,一个是十个“撤消”之前的对象)以及在它们之间应用的命令列表来潜在地节省内存。

要进行“撤消”,您重新执行除最后一个命令对象之外的所有对象,将其用作新的当前对象,然后删除最后一个命令(或将其保存为“重做”对象)。每次执行新操作时,都会更新当前对象,将关联的命令添加到列表中,然后(如果列表长度超过十个命令)从撤消列表的开头对对象执行第一个命令并丢弃列表中的第一个命令。

您也可以执行各种其他检查点系统,包括可变数量的系统完整表示以及它们之间可变数量的命令。但它离你引用的原始想法越来越远,越来越像一个典型的可变系统。但是,它确实避免了使命令始终可逆的问题;您只需要向前应用命令而不是反向应用命令。

SVN 和其他版本控制系统实际上是基于磁盘或网络的撤消和重做形式。

于 2009-11-28T16:45:20.457 回答