PassFront
  1. PassFront
  2. База знаний
  3. Поведенческие паттерны

Как паттерн Memento помогает реализовать undo и redo?

Поведенческие паттерны

Memento сохраняет снимок внутреннего состояния объекта, не нарушая инкапсуляцию: снимок создаёт и применяет сам объект (Originator), а хранитель (Caretaker) держит снимки, не заглядывая внутрь.

Роли

  • Originator — save() возвращает снимок, restore(m) откатывается к нему.
  • Memento — непрозрачный неизменяемый снимок.
  • Caretaker — стеки undo и redo.

Undo/redo на двух стеках

  1. Перед изменением снимок кладётся в undo, стек redo очищается.
  2. Undo: текущее состояние → redo, восстановление из undo.pop().
  3. Redo — зеркально.
class Editor {
  #text = '';
  #cursor = 0;
  type(s) { this.#text += s; this.#cursor = this.#text.length; }
  save() { return Object.freeze({ text: this.#text, cursor: this.#cursor }); }
  restore(m) { this.#text = m.text; this.#cursor = m.cursor; }
  get value() { return this.#text; }
}
const editor = new Editor();
const undo = [];
undo.push(editor.save()); editor.type('Привет');
undo.push(editor.save()); editor.type(', мир');
editor.restore(undo.pop());
console.log(editor.value); // Привет

Цена и альтернативы

  • Полные снимки дороги: 10 МБ × 100 шагов = 1 ГБ. Спасают лимит истории, дельты и structural sharing (как в Immer).
  • Подход через Command хранит обратные операции вместо состояний — памяти меньше, но у каждой команды должен быть корректный undo().

Коротко для собеседования

Memento позволяет откатить объект к снимку, при этом снимок создаёт и читает только сам объект, а хранитель просто держит стеки undo и redo. Главная цена — память на полные снимки, её снижают лимитом истории, дельтами или хранением обратных команд.

Другие вопросы раздела