Memento
Capture an object's state as an opaque snapshot so it can be restored later — without exposing its insides.
Big idea
A Memento is a snapshot of an object's internal state, created by the object itself and handed to someone else to keep. The keeper (a history, a save slot) can store and return snapshots but can't look inside or change them — so you get undo, checkpoints, and rollbacks without breaking encapsulation.
The problem it solves
A drawing app needs undo. The easy way: let the history class read every field of the canvas — shapes, layers, selection, zoom — and copy them. Now the history depends on the canvas's private layout; add a field and undo silently stops restoring it. Make the fields public to allow the copying, and every other class can now poke at them too.
Think of it like
A game's save point. The game writes your entire state into a save file; the console's storage keeps the file but has no idea what's in it. When you load, the game reads its own file back. The storage didn't need to understand inventories or health bars — it just kept the box safe.
Structure
- Originator (
Character) — creates snapshots of itself and restores from them. - Memento (
Snapshot) — immutable; its contents are meaningful only to the originator. - Caretaker (
Checkpoints) — decides when to save and restore, never what.
In code
import copy
class Snapshot:
def __init__(self, label, state):
self.label = label
self._state = state # opaque to everyone but the originator
class Character:
def __init__(self):
self._hp, self._x, self._inventory = 100, 0, ["torch"]
def act(self, move, damage=0, item=None):
self._x += move
self._hp -= damage
if item:
self._inventory.append(item)
def save(self, label):
return Snapshot(label, copy.deepcopy((self._hp, self._x, self._inventory)))
def restore(self, snapshot):
self._hp, self._x, self._inventory = copy.deepcopy(snapshot._state)
def __str__(self):
return f"hp={self._hp} x={self._x} items={self._inventory}"
class Checkpoints: # the caretaker
def __init__(self):
self._stack = []
def push(self, snapshot):
self._stack.append(snapshot)
def pop(self):
return self._stack.pop()
hero, saves = Character(), Checkpoints()
saves.push(hero.save("start"))
hero.act(5, item="key")
saves.push(hero.save("found key"))
hero.act(3, damage=80, item="cursed ring")
print("now: ", hero)
snap = saves.pop()
hero.restore(snap)
print("restored:", hero, f"({snap.label})")
hero.act(-2)
hero.restore(saves.pop())
print("restored:", hero)output
now: hp=20 x=8 items=['torch', 'key', 'cursed ring']
restored: hp=100 x=5 items=['torch', 'key'] (found key)
restored: hp=100 x=0 items=['torch']Run and edit it in the app.
The deep copy matters: without it, the snapshot would share the inventory list with the live character, and picking up the cursed ring would also "change the past".
Who should be able to read a memento's contents?
Watch it
Memento or Command for undo?
- Memento — snapshot the whole state before each change; undo restores it. Simple and robust, but memory-heavy for large state.
- Command — each action knows how to reverse itself. Light on memory, but every command needs a correct inverse.
- Many editors combine them: commands that store a small memento of only what they change.
When to use it — and when not to
Use it for undo, checkpoints and rollbacks (games, wizards, transactions), and "cancel" on edit dialogs. Beware with large or frequently changing state — snapshots can eat memory fast; consider storing diffs, limiting history depth, or using commands instead.
Pros and cons
| Pros | Cons |
|---|---|
| Undo and rollback without exposing internals | Snapshots can use a lot of memory |
| Caretaker stays simple and generic | Deep vs shallow copy bugs (see Prototype) |
| Originator controls exactly what is saved | Caretakers must prune old snapshots |
How it relates
- Command is the other undo mechanism; they're often used together.
- Prototype also copies state, but to create a new object rather than restore an old one.
- Iterator state can be captured as a memento to resume traversal later.
- At system scale, database snapshots and event sourcing play the same role.
An image editor stores a full memento of a 50 MB image after every brush stroke. What's the most likely problem?
Key terms
- Memento — An opaque snapshot of an object's state that can be restored later.
- Originator — The object that creates mementos of itself and restores from them.
- Caretaker — The object that stores mementos and decides when to save or restore, without reading them.
- Checkpoint — A saved state you can roll back to.