Отмена/Восстановление с неизменными объектами

Я считал следующее в статье

Неизменные объекты особенно удобны для реализации определенных общих идиом, таких как отмена/восстановление и abortable транзакции. Возьмите отмену, например. Общая техника для реализации отмены должна сохранить стопку объектов, которые так или иначе знают, как выполнить каждую команду наоборот (так называемый "Шаблон"команда""). Однако выяснение, как выполнить команду наоборот, может быть хитрым. Более простая техника состоит в том, чтобы поддержать стопку неизменных объектов, представляющих состояние системы между последовательными командами. Затем для отмены команды Вы просто возвращаетесь назад к предыдущему состоянию системы (и, вероятно, сохраните текущее состояние на стеке повторного выполнения).

Однако статья не показывает хороший практический пример того, как неизменные объекты могли использоваться для реализации операций "отмены". Например... удаляя 10 электронных писем из ящика входящих сообщений Gmail. После того как Вы делаете это, это имеет опцию отмены. Как неизменное возразило бы справке в этом отношении?

6
задан phuclv 12 August 2019 в 06:40
поделиться

1 ответ

The immutable objects would hold the entire state of the system, so in this case you'd have object A that contains the original inbox, and then object B that contains the inbox with ten e-mails deleted, and (in effect) a pointer back from B to A indicating that, if you do one "undo", then you stop using B as the state of the system and start using A instead.

However, Gmail inboxes are far too large to use this technique. You'd use it on documents that can actually be stored in a fairly small amount of memory, so that you can keep many of them around for multi-level undo.

If you want to keep ten levels of undo, you can potentially save memory by only keeping two immutable objects - one that is current, and one that is from ten "undos" ago - and a list of Commands that were applied between them.

To do an "undo", you re-execute all but the last Command object, use that as the new current object, and erase the last Command (or save it as a "Redo" object). Every time you do a new action, you update the current object, add the associated Command to the list, and then (if the list is more than ten Commands long) you execute the first Command on the object from the start of the undo list and throw away the first Command on the list.

You can do various other checkpointing systems as well, involving a variable number of complete representations of the system as well as a variable number of Commands between them. But it gets further and further from the original idea that you cited and becomes more and more like a typical mutable system. It does, however, avoid the problem of making Commands consistently reversible; you need only ever apply Commands to an object forward and not reverse.

SVN and other version control systems are effectively a disk- or network-based form of undo-and-redo.

6
ответ дан 17 December 2019 в 02:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: