Что это такое
Паттерн Memento сохраняет снимок состояния объекта, чтобы его можно было восстановить позже — не показывая никому внутреннее устройство объекта. Объект сам создаёт снимок и сам восстанавливается из него; внешний мир только хранит снимки.
Это тот самый паттерн, который стоит за «отменой до сохранённой точки», черновиками и контрольными точками.
Пример: снимки редактора
save() возвращает снимок; restore() принимает его обратно. Ошибка, сделанная между этими вызовами, просто исчезает.
{ ...this } копирует значения полей объекта в новый объект. Эта копия важна: если бы снимком был сам объект, каждая последующая правка меняла бы и «старое состояние». Для состояния, в котором есть вложенные объекты или массивы, используйте structuredClone(this) — spread копирует только верхний уровень.
Сохранить, сломать, восстановить
Снимок был сделан, когда текст был Привет, мир!. После плохой правки редактор выводит Привет, мри! ой, а затем restore(saved) возвращает в точности прежний текст — владелец снимка ни разу не заглянул внутрь него.
Вывод: программа на TypeScript и захваченный вывод
// Мементо: сохранённый снимок состояния.
type Snapshot = {
readonly text: string
}
class Editor {
text: string = ""
// Spread копирует значения полей, поэтому поздние правки до них не доходят.
save(): Snapshot {
return { ...this }
}
restore(snapshot: Snapshot): void {
this.text = snapshot.text
}
}
const editor = new Editor()
editor.text = "Привет, мир!"
const saved = editor.save()
editor.text = "Привет, мри! ой"
console.log("сейчас:", editor.text)
editor.restore(saved)
console.log("отмена:", editor.text)
Когда его использовать
Используйте его для контрольных точек и отката: отмена в редакторе, сохранения в играх, «восстановить настройки по умолчанию», шаги транзакции, которые может понадобиться откатить.
Откажитесь от него, когда состояние — это одно-два простых значения: просто сохраните старое значение в переменной. И сравните с Command: команды отменяют шаг за шагом, а мементо возвращает сразу к сохранённой точке.
Плюсы и минусы
Плюсы: настоящий откат без раскрытия внутреннего устройства; снимки — это простые значения, которые можно хранить в массиве для многоуровневой отмены; пометка их полей как readonly не даёт владельцам их изменять.
Минусы: снимки большого состояния быстро расходуют память; легко ошибиться, решая, что должно попасть в снимок (и поддерживая его полноту по мере роста класса).