Memento
Capture and restore an object's previous state without exposing a single one of its private fields to the outside world.
The problem
You are building a text editor and, like every app since 1984, it needs undo. The direct approach looks obvious: before each operation, copy the state of everything into storage, and on undo, copy it back.
Then you try to write the copying code and hit a wall. The editor keeps its text, cursor coordinates, scroll position, and selection width in private fields, exactly where they belong. An outside class cannot read them. So you shrug and make everything public.
Now two things are broken. The editor's internals are exposed to the entire program, and the snapshot code is welded to its field list, so every refactor of the editor drags the history class along with it. Restricting access makes snapshots impossible; allowing access makes the design fragile. That is not a trade-off, that is a dead end.
The solution
The dead end exists because the wrong object is doing the work. A history class that reads the editor's private fields is trespassing. Stop trespassing and ask instead.
Memento moves snapshot duty to the object that owns the state, called the originator. It produces a memento: a small immutable object holding a copy of that state, which nobody else can read. Other objects, called caretakers, may hold the memento, stack it, and hand it back for restoration, but the contents stay sealed. A caretaker sees metadata at most - when the snapshot was taken, what operation it precedes.
- 1The user hits Bold. Before anything mutates, the caretaker tells the command to take a safety copy.
- 2The command does not read the editor. It asks the editor to snapshot itself, which is the entire trick of the pattern.
- 3The editor pours its private fields into a fresh memento through the constructor. Private data never leaves the family.
- 4The command stashes the memento as an opaque token. It could not read the text inside it if it tried.
- 5Now the command actually does its job and scribbles all over the editor state.
- 6The user regrets everything. The history pops the most recent command and asks it to undo.
- 7The command hands the memento back. Restoration logic lives in the memento, not in the caretaker.
- 8The memento pushes the old values back into its own editor through setters. Time travel, encapsulation intact.
Structure
Languages with nested classes get the strictest version: nest the memento
inside the originator so the outer class can read its fields while everyone
else sees an opaque handle. Elsewhere you extract a marker interface that
declares only metadata, and caretakers hold that. A third variant, shown below,
links each memento to the originator that made it and puts restore() on the
memento, which frees the caretaker from knowing the originator type at all.
Code
Same example three ways: a text editor with an undo stack, where each command carries the snapshot it took before running.
When to use it
- You need undo, redo, or a history of states, and the state you must capture lives in private fields.
- You need transactional rollback: take a snapshot, attempt a risky multi-step operation, and restore if any step fails.
- Direct access to an object's fields or setters would violate its encapsulation, but something outside it still has to manage its history.
Pitfalls
- RAM is the bill. Full state copies at high frequency will bury you. Batch small changes into one undoable unit, or store deltas instead of full states.
- Lifecycle leaks. Caretakers must know when a memento is obsolete and release it, otherwise the history stack keeps dead objects alive forever.
- Dynamic languages cannot enforce the seal. Python, JavaScript, and PHP let a determined caller reach into any object. The pattern still buys you clean coupling, but treat the privacy as a contract, not a guarantee.
- Mementos holding external handles. A snapshot containing an open socket or file descriptor restores into a world that has moved on. Capture values, not connections.
Don't confuse it with
- Prototype. Prototype clones the entire live object, secrets and all, and the clone is a fully functional peer. Memento produces a deliberately inert, unreadable snapshot. When the object is simple and self-contained, Prototype is the cheaper answer and the GoF book says so plainly.
- Serialization. Serializing to JSON is a snapshot too, but it is the exact opposite move on encapsulation: the state is now text that anything can read and edit. Serialization is for crossing process boundaries; Memento is for keeping state inside one and hiding it while it waits.
- Command. Command captures an operation, Memento captures state. In a real undo system they work together, with the command acting as caretaker for the snapshot it took just before executing.
- Iterator. Pairing them is a known trick: a memento can capture an iteration position so you can roll a traversal back.
Check yourself
Who is allowed to read the data inside a memento?