Я придумал что-то похожее на шаблон Memento, но достаточно отличающееся, чтобы я думаю, что оно должно быть опубликовано. Когда пользователь начинает сеанс редактирования, я дублирую целевой объект на временный объект в базе данных. Все последующие операции редактирования влияют на дубликат. Вместо сохранения состояния объекта в памятке при каждом изменении я сохраняю операцию объектов. Когда я применяю операцию к объекту, она возвращает обратную операцию, которую я сохраняю.
Операции сохранения намного дешевле для меня, чем сувениры, поскольку операции могут быть описаны с помощью нескольких небольших элементов данных, тогда как редактируемый объект намного больше. Также я применяю операции, когда иду, и сохраняю отмены, так что временная переменная в БД всегда соответствует версии в браузере пользователя. Мне никогда не придется воспроизводить коллекцию изменений; временная операция всегда находится всего в одной операции от следующей версии.
Чтобы реализовать «отмену», я вытаскиваю последний объект отмены из стека (как бы - путем извлечения самой последней операции для временного объекта из БД), применяю его к временному и возвращаю преобразованное временное. Я мог бы также поместить получившуюся операцию в стек повторного выполнения, если бы хотел реализовать повтор.
Для реализации «сохранения изменений», т. Е. Фиксации, я деактивирую и отмечаю метку времени исходного объекта и активирую временный объект на его месте.
Для реализации "отмены", то есть отката, я ничего не делаю! Конечно, я мог бы удалить временный, потому что у пользователя нет возможности получить его после окончания сеанса редактирования, но мне нравится сохранять отмененные сеансы редактирования, чтобы я мог запускать статистику по ним, прежде чем очищать их с помощью задания cron. .