Неизменяемые объекты будут содержать все состояние системы, поэтому в этом случае у вас будет объект A, который содержит исходный почтовый ящик, а затем объект B, который содержит почтовый ящик с десятью удаленными электронными письмами, и (в действительности ) указатель назад от B к A, указывающий, что, если вы сделаете одну «отмену», то вы перестанете использовать B в качестве состояния системы и вместо этого начнете использовать A.
Однако почтовые ящики Gmail слишком велики, чтобы использовать эту технику. Вы будете использовать его в документах, которые на самом деле могут храниться в довольно небольшом объеме памяти, так что вы можете хранить многие из них для многоуровневой отмены.
Если вы хотите сохранить десять уровней отмены, вы можете потенциально сохранить память, сохранив только два неизменяемых объекта - один текущий и один из десяти «отмен» назад - и список команд, которые применялись между им.
Чтобы выполнить «отмену», вы повторно выполняете все объекты, кроме последнего объекта Command, используете их в качестве нового текущего объекта и удаляете последнюю команду (или сохраняете ее как объект «Redo»). Каждый раз, когда вы выполняете новое действие, вы обновляете текущий объект, добавляете связанную команду в список, а затем (если длина списка превышает десять команд) вы выполняете первую команду на объекте с начала списка отмены. и выбросить первую команду в списке.
Вы также можете использовать различные другие системы контрольных точек, включая переменное число полных представлений системы, а также переменное число команд между ними. Но это все дальше и дальше от первоначальной идеи, которую вы цитировали, и становится все более похожей на типичную изменяемую систему. Это, однако, позволяет избежать проблемы превращения команд в последовательно обратимые; вам нужно только применять Команды к объекту вперед, а не назад.
SVN и другие системы контроля версий - это, по сути, дисковая или сетевая форма отмены и восстановления.