На мой взгляд, UNDO / REDO можно реализовать двумя способами. 1. Командный уровень (называемый командным уровнем Отменить / Вернуть) 2. Уровень документа (называемый глобальным Отменить / Вернуть)
Командный уровень: как отмечается во многих ответах, это эффективно достигается с помощью шаблона Memento. Если команда также поддерживает ведение журнала действия, повторение легко поддерживается.
Ограничение: как только область действия команды исчерпана, отменить / повторить невозможно, что приводит к отмене / повторному выполнению на уровне документа (глобальном).
Я предполагаю, что ваш случай вписался бы в глобальную отмену / повтор, поскольку он подходит для модели, которая требует много места в памяти. Кроме того, это также подходит для выборочной отмены / повтора. Есть два примитивных типа
- Отменить / повторить всю память
- Уровень объекта Отменить Повторить
В режиме «Отменить / повторить всю память» вся память рассматривается как связанные данные (такие как дерево, список или граф), а память управляется приложением, а не ОС. Таким образом, операторы new и delete, если в C ++ перегружены, чтобы содержать более конкретные структуры для эффективной реализации таких операций, как. Если какой-либо узел изменен, b. хранение и очистка данных и т. д. Принцип его работы заключается в том, чтобы скопировать всю память (при условии, что выделение памяти уже оптимизировано и управляется приложением с использованием передовых алгоритмов) и сохранить ее в стеке. Если запрашивается копия памяти, древовидная структура копируется в зависимости от необходимости иметь мелкую или глубокую копию. Глубокая копия делается только для той переменной, которая изменена. Поскольку каждая переменная выделяется с использованием настраиваемого распределения, последнее слово остается за приложением, когда его удалять, если это необходимо. Вещи становятся очень интересными, если нам нужно разделить Undo / Redo, когда случается так, что нам нужно программно выборочно отменить / Redo набор операций. В этом случае только эти новые переменные, или удаленные переменные, или измененные переменные получают флаг, так что Undo / Redo отменяет / повторяет только эту память. Вещи становятся еще более интересными, если нам нужно выполнить частичную Undo / Redo внутри объекта. В таком случае используется более новая идея «паттерна посетителя». Это называется «Отменить / повторить на уровне объекта». или удаленным переменным, или измененным переменным присваивается флаг, так что Undo / Redo отменяет / повторяет только эту память. Вещи становятся еще более интересными, если нам нужно выполнить частичную Undo / Redo внутри объекта. В таком случае используется более новая идея «паттерна посетителя». Это называется «Отменить / повторить на уровне объекта». или удаленным переменным, или измененным переменным присваивается флаг, так что Undo / Redo отменяет / повторяет только эту память. Вещи становятся еще более интересными, если нам нужно выполнить частичную Undo / Redo внутри объекта. В таком случае используется более новая идея «паттерна посетителя». Это называется «Отменить / повторить на уровне объекта».
- Отменить / повторить на уровне объекта: когда вызывается уведомление об отмене / повторении, каждый объект реализует операцию потоковой передачи, при которой стример получает от объекта старые / новые данные, которые запрограммированы. Данные, которые не могут быть нарушены, остаются нетронутыми. Каждый объект получает стример в качестве аргумента, и внутри вызова UNDo / Redo он передает / отменяет поток данных объекта.
И 1, и 2 могут иметь такие методы, как 1. BeforeUndo () 2. AfterUndo () 3. BeforeRedo () 4. AfterRedo (). Эти методы должны быть опубликованы в основной команде Undo / redo (а не в контекстной команде), чтобы все объекты также реализовали эти методы для получения определенного действия.
Хорошая стратегия - создать гибрид 1 и 2. Прелесть в том, что эти методы (1 и 2) сами используют шаблоны команд.