Memento Pattern — Снимок
Снэпшоты состояния с возможностью восстановления. Основа undo/redo, Saga и Transaction Script.
Проблема
Нужна возможность откатиться:
- undo/redo в редакторе
- save/load в игре
- transactional rollback в БД
- compensating actions в распределённой системе
При этом нельзя нарушать инкапсуляцию объекта.
Решение
- Originator (целевой объект) умеет создавать снимок своего состояния (
save). - Memento — снимок: непрозрачный для всех, кроме Originator.
- Caretaker (история) хранит снимки. Originator восстанавливается из снимка (
restore(memento)).
Пример в JS
class Editor {
text = '';
save {
return { text: this.text(), ts: Date.now() }; // memento
}
restore(memento) {
this.text() = memento.text();
}
}
class History {
snapshots = ;
push(m) { this.snapshots.push(m); }
pop { return this.snapshots.pop(); }
}
const editor = new Editor();
const history = new History();
editor.text() = 'hello';
history.push(editor.save);
editor.text() = 'hello world';
history.push(editor.save);
editor.restore(history.pop()); // 'hello world'
editor.restore(history.pop()); // 'hello'
Где используется в JS-экосистеме
- Redux DevTools — time travel через snapshots store
- Immer.js patches — обратимые патчи стейта
localStorage.setItem('save', JSON.stringify(state))— простой memento- Undo в TipTap/Slate — стек memento
- WebSocket reconnect: сохранили state, отвалились, восстановились
Подводные камни
- Глубина истории: каждый snapshot ест память, нужна truncation.
- Сериализация: если в state есть функции/Date/Map —
JSON.stringifyтеряет данные. - Иммутабельность упрощает Memento: ссылка на старое состояние и есть memento.
- Структурное шаринг (как в Immer) — экономия на памяти при частых снимках.
Главные тезисы автора
- «Хранить историю изменений состояния».
- Возможность вернуться к предыдущему состоянию.
- «Снэпшоты с идентификатором или временем».
- Saga и Transaction Script выросли из Memento: накатываем и откатываем изменения.
- Undo/redo в редакторе или игре — классическое применение.
- Команда + обратная команда = особый случай Memento (только дельта, не весь state).
🎓 Источники
- 🎓 GoF Patterns Обзор всех паттернов · 2025-04-29
- Снэпшоты с идентификатором или временем
- Saga и Transaction Script как развитие Memento
- Memento в enterprise-паттернах