Отменить / Повторить с неизменными объектами - PullRequest
6 голосов
/ 28 ноября 2009

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

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

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

1 Ответ

6 голосов
/ 28 ноября 2009

Неизменяемые объекты будут содержать все состояние системы, поэтому в этом случае у вас будет объект A, который содержит исходный почтовый ящик, а затем объект B, который содержит почтовый ящик с десятью удаленными электронными письмами, и (в действительности ) указатель назад от B к A, указывающий, что, если вы сделаете одну «отмену», то вы перестанете использовать B в качестве состояния системы и вместо этого начнете использовать A.

Однако почтовые ящики Gmail слишком велики, чтобы использовать эту технику. Вы будете использовать его в документах, которые на самом деле могут храниться в довольно небольшом объеме памяти, так что вы можете хранить многие из них для многоуровневой отмены.

Если вы хотите сохранить десять уровней отмены, вы можете потенциально сохранить память, сохранив только два неизменяемых объекта - один текущий и один из десяти «отмен» назад - и список команд, которые применялись между им.

Чтобы выполнить «отмену», вы повторно выполняете все объекты, кроме последнего объекта Command, используете их в качестве нового текущего объекта и удаляете последнюю команду (или сохраняете ее как объект «Redo»). Каждый раз, когда вы выполняете новое действие, вы обновляете текущий объект, добавляете связанную команду в список, а затем (если длина списка превышает десять команд) вы выполняете первую команду на объекте с начала списка отмены. и выбросить первую команду в списке.

Вы также можете использовать различные другие системы контрольных точек, включая переменное число полных представлений системы, а также переменное число команд между ними. Но это все дальше и дальше от первоначальной идеи, которую вы цитировали, и становится все более похожей на типичную изменяемую систему. Это, однако, позволяет избежать проблемы превращения команд в последовательно обратимые; вам нужно только применять Команды к объекту вперед, а не назад.

SVN и другие системы контроля версий - это, по сути, дисковая или сетевая форма отмены и восстановления.

...