Перейти к основному содержимому

Что это такое

Паттерн Memento сохраняет снимок состояния объекта, чтобы его можно было восстановить позже — не показывая никому внутреннее устройство объекта. Объект сам создаёт снимок и сам восстанавливается из него; внешний мир только хранит снимки.

Это тот самый паттерн, который стоит за «отменой до сохранённой точки», черновиками и контрольными точками.


Пример: снимки редактора

save() возвращает снимок; restore() принимает его обратно. Ошибка, сделанная между этими вызовами, просто исчезает.

{ ...this } копирует значения полей объекта в новый объект. Эта копия важна: если бы снимком был сам объект, каждая последующая правка меняла бы и «старое состояние». Для состояния, в котором есть вложенные объекты или массивы, используйте structuredClone(this) — spread копирует только верхний уровень.

Сохранить, сломать, восстановить

Снимок был сделан, когда текст был Привет, мир!. После плохой правки редактор выводит Привет, мри! ой, а затем restore(saved) возвращает в точности прежний текст — владелец снимка ни разу не заглянул внутрь него.

Prompt
Напишите программу на TypeScript с паттерном Memento: класс Editor с полем text, тип Snapshot с полем text, помеченным readonly, метод save, возвращающий снимок, созданный копированием через spread, и метод restore, принимающий снимок. Напишите хороший текст, сохраните его, сделайте плохую правку, выведите её, восстановите снимок и выведите возвращённый текст.
Вывод: программа на TypeScript и захваченный вывод

Когда его использовать

Используйте его для контрольных точек и отката: отмена в редакторе, сохранения в играх, «восстановить настройки по умолчанию», шаги транзакции, которые может понадобиться откатить.

Откажитесь от него, когда состояние — это одно-два простых значения: просто сохраните старое значение в переменной. И сравните с Command: команды отменяют шаг за шагом, а мементо возвращает сразу к сохранённой точке.


Плюсы и минусы

Плюсы: настоящий откат без раскрытия внутреннего устройства; снимки — это простые значения, которые можно хранить в массиве для многоуровневой отмены; пометка их полей как readonly не даёт владельцам их изменять.

Минусы: снимки большого состояния быстро расходуют память; легко ошибиться, решая, что должно попасть в снимок (и поддерживая его полноту по мере роста класса).