Что это такое
Паттерн Снимок (Memento) сохраняет снимок состояния объекта, чтобы позже его можно было восстановить, — и при этом никому не показывает внутреннее устройство объекта. Объект сам создаёт снимок и сам восстанавливается из него; внешний мир лишь хранит снимки.
Этот паттерн стоит за «отменой до сохранённой точки», черновиками и контрольными точками.
Пример: снимки редактора
save() возвращает снимок — замороженный dataclass, который его владелец не может изменить; restore() принимает его обратно. Ошибка, сделанная в промежутке, просто исчезает.
Сохранить, испортить, восстановить
Снимок был сделан, пока текст был правильным. После неудачной правки restore(saved) возвращает в точности прежнее состояние — владелец снимка ни разу не заглядывал внутрь него.
Вывод: полная программа на Python
from dataclasses import dataclass
# Снимок (memento): сохранённый снимок состояния, замороженный,
# чтобы его владелец не мог его изменить.
@dataclass(frozen=True)
class Snapshot:
text: str
class Editor:
def __init__(self) -> None:
self.text = ""
def save(self) -> Snapshot:
return Snapshot(text=self.text)
def restore(self, snapshot: Snapshot) -> None:
self.text = snapshot.text
e = Editor()
e.text = "Hello, world!"
saved = e.save()
e.text = "Hello, wrold! oops"
print("сейчас:", e.text)
e.restore(saved)
print("отмена:", e.text)
Когда его использовать
Используйте его для контрольных точек и отката: отмена в редакторе, сохранения в играх, «сброс к настройкам по умолчанию», транзакционные шаги, которые может понадобиться отменить.
Не используйте его, когда состояние — это одно-два простых значения: просто сохраните старое значение в переменной. И сравните с паттерном Команда: команды отменяют действия шаг за шагом, а снимки возвращают сразу к сохранённой точке.
Плюсы и минусы
Плюсы: настоящий откат без раскрытия внутреннего устройства; снимки — это простые значения, которые можно хранить в списках для многоуровневой отмены.
Минусы: снимки большого состояния быстро расходуют память; легко ошибиться, решая, что должно входить в снимок (и поддерживая его полноту по мере роста класса).