Overview
The Memento pattern captures an object's internal state as a snapshot (memento) so it can be restored later, without exposing that state to other objects. The originator creates and restores mementos; a caretaker (history manager) stores them but cannot read or modify their contents.
Memento enables undo, checkpoints, versioning, and transactional rollback while preserving encapsulation. It is the snapshot-based alternative to Command's inverse operations, simpler to implement but more memory-hungry for large states.
The game saves your progress into a slot you cannot edit. If you fail, you reload the save and continue from exactly that state.
When to use it
- Undo or rollback by restoring previous states.
- Checkpoints in games, editors, or wizards.
- State is complex to reverse operation by operation.
Where it shows up in interviews
Recognize it when: restore previous states.
- Design a text editor with undo
- Design a game with save points
- Design a form wizard
Where it is used in real software
SAVEPOINT and ROLLBACK TO restore transaction state to a checkpoint.
Stored immutable states let developer tools jump to any previous state.
Hypervisors snapshot VM state for rollback.
Key terms
- Originator
- Object whose state is saved.
- Memento
- Opaque snapshot of the state.
- Caretaker
- Stores mementos; never inspects them.
- Incremental memento
- Stores only changes to save memory.
How it works, step by step
- 1Identify the state to save
Only what is needed to restore.
- 2Create an immutable memento type
Opaque to outsiders.
- 3Originator: save() and restore(m)
Only it can read the memento.
- 4Caretaker stores a history
Stack or list, with a cap.
- 5Restore on undo
Pop and pass back to the originator.
Editor snapshots
Caretaker pushes a memento before each change
| Action | Text | History (mementos) |
|---|---|---|
| type 'Hi' | Hi | [''] |
| type ' there' | Hi there | ['', 'Hi'] |
| undo | Hi | [''] |
| undo | (empty) | [] |
NOWAction: type 'Hi' | Text: Hi | History (mementos): ['']
Each undo restores an exact previous state without the caretaker knowing how text is stored.
Implementation
class EditorMemento { // Opaque: fields are private and readonly; only Editor uses them via the accessor below constructor(private readonly text: string, private readonly cursor: number) {} /** @internal */ restoreInto(apply: (text: string, cursor: number) => void) { apply(this.text, this.cursor); }} class Editor { private text = ""; private cursor = 0; type(s: string) { this.text = this.text.slice(0, this.cursor) + s + this.text.slice(this.cursor); this.cursor += s.length; } save() { return new EditorMemento(this.text, this.cursor); } restore(m: EditorMemento) { m.restoreInto((t, c) => { this.text = t; this.cursor = c; }); } toString() { return this.text; }} class History { private stack: EditorMemento[] = []; constructor(private editor: Editor, private limit = 100) {} checkpoint() { this.stack.push(this.editor.save()); if (this.stack.length > this.limit) this.stack.shift(); } undo() { const m = this.stack.pop(); if (m) this.editor.restore(m); }} const editor = new Editor();const history = new History(editor);history.checkpoint(); editor.type("Hi");history.checkpoint(); editor.type(" there");history.undo(); // "Hi"Complexity and performance
Full snapshot.
Cap or use diffs.
Trade-offs
Snapshots are easy and reliable but costly for large states; commands with inverse operations or structural sharing reduce memory.
Keeping mementos opaque is easier with nested classes (Java) than in JavaScript.
Variants and related techniques
Immutable structures share unchanged parts across versions.
Save to disk for crash recovery.
Common mistakes
- Mementos sharing mutable collections with the originator.
Fix: Copy collections into the snapshot.
- Unbounded history.
Fix: Limit size or compress older snapshots.
Interview questions
Memento vs Command for undo?
Memento stores full state snapshots and restores them, which is simple but memory heavy. Command stores the operation and knows how to reverse it, which is compact but requires correct inverse logic for every operation.
Why is the caretaker not allowed to read the memento?
To preserve encapsulation: only the originator understands its internal state, so the caretaker just stores and returns snapshots.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| Form wizard with back button | Easy | Snapshots. |
| Drawing canvas with capped undo history | Medium | Memory limits. |