Что это такое
Паттерн Memento сохраняет снимок состояния объекта, чтобы это состояние можно было восстановить позже — не показывая никому внутреннее устройство объекта. Объект сам создаёт снимок и сам восстанавливается из него; внешний мир просто хранит снимки.
Это паттерн, который стоит за «отменой до сохранённой точки», черновиками и контрольными точками.
Пример: снимки редактора
Save() возвращает снимок; Restore() принимает его обратно. Ошибка, сделанная между этими вызовами, просто исчезает.
Сохранить, испортить, восстановить
Снимок был сделан, пока текст был правильным. После неудачной правки Restore(saved) возвращает в точности прежнее состояние — при этом владелец снимка ни разу не заглядывал внутрь него.
Вывод: программа на Go и захваченный вывод
package main
import "fmt"
type Editor struct {
text string
}
// Memento: сохранённый снимок состояния.
type Snapshot struct {
text string
}
func (e *Editor) Save() Snapshot {
return Snapshot{text: e.text}
}
func (e *Editor) Restore(s Snapshot) {
e.text = s.text
}
func main() {
e := &Editor{}
e.text = "Привет, мир!"
saved := e.Save()
e.text = "Привет, мри! ой"
fmt.Println("сейчас:", e.text)
e.Restore(saved)
fmt.Println("отмена:", e.text)
}
Когда его использовать
Используйте для контрольных точек и отката: отмена в редакторе, сохранения в играх, «восстановить настройки по умолчанию», шаги транзакции, которые может понадобиться отменить.
Не используйте, когда состояние — это одно-два простых значения: достаточно сохранить старое значение в переменной. И сравните с Command: команды отменяют шаг за шагом, а мементо возвращает сразу к сохранённой точке.
Плюсы и минусы
Плюсы: настоящий откат без раскрытия внутреннего устройства; снимки — это простые значения, которые можно хранить в списках для многоуровневой отмены.
Минусы: снимки большого состояния быстро расходуют память; легко ошибиться, решая, что именно должно входить в снимок (и поддерживая его полноту по мере роста типа).