Я успешно реализовал сложные системы отмены, используя шаблон Memento - очень легко, и имеет преимущество, естественно, также предоставляя платформу Redo. Более тонкое преимущество заключается в том, что совокупные действия могут содержаться и в одной отмене.
В двух словах, у вас есть две стопки объектов сувениров. Один для отмены, другой для повторения. Каждая операция создает новый сувенир, который в идеале будет вызывать изменение состояния вашей модели, документа (или чего-либо еще). Это добавляется в стек отмены. Когда вы выполняете операцию отмены, в дополнение к выполнению действия «Отменить» для объекта Memento для повторного изменения модели, вы также извлекаете объект из стека отмены и помещаете его прямо в стек повторения.
Каким образом реализуется метод изменения состояния вашего документа, полностью зависит от вашей реализации. Если вы можете просто выполнить вызов API (например, ChangeColour (r, g, b)), то перед ним следует запрос, чтобы получить и сохранить соответствующее состояние. Но шаблон также будет поддерживать создание глубоких копий, снимков памяти, создание временных файлов и т. Д. - все зависит от вас, поскольку это просто реализация виртуального метода.
Для выполнения агрегатных действий (например, пользователь Shift-выбирает загрузку объектов для выполнения операций, таких как удаление, переименование, изменение атрибута), ваш код создает новый стек отмены в виде отдельного сувенира и передает его фактическая операция для добавления отдельных операций. Таким образом, ваши методы действий не должны (а) иметь глобальный стек, о котором нужно беспокоиться, и (б) могут быть закодированы одинаково, независимо от того, выполняются ли они изолированно или как часть одной агрегатной операции.
Многие системы отмены находятся только в оперативной памяти, но вы можете сохранить стек отмены, если хотите, я думаю.