Card 01/ 08
Memento Pattern: Saving and Restoring State Without Exposing It
Undo needs a copy of the editor's state, and nobody but the editor should be able to read it.
The Memento pattern lets an object save its own state as a snapshot, called a memento, that another object can keep but not read. Later the memento is handed back, and the object restores itself from it. This card covers the problem that calls for it, the intent, and when it fits.
The problem is that saving state from outside means making it public. An undo feature for a text editor needs the text, the cursor position and the selection from before each change. If the undo code copies those fields itself, the editor must expose all of them, and any code that can read them for undo can also change them. Each new field the editor adds must also be remembered in the undo code.
Without the patternthe caller copies the fields
saved = (editor.text, editor.cursor)
editor.type("hello")
editor.text, editor.cursor = savedThe undo code knows every field, and can set them to anything.
With the patternthe editor makes and reads its own snapshot
saved = editor.save()
editor.type("hello")
editor.restore(saved)The undo code holds saved, and never looks inside.
The Gang of Four state the intent as: without violating encapsulation, capture and externalise an object's internal state so that the object can be restored to this state later. Encapsulation is the rule that an object's fields are reached only through its own methods; the memento keeps that rule while the state leaves the object.
A sealed envelope is a familiar picture. The editor writes its state on a card, seals it, and hands it over; the history list keeps the envelopes in order and returns one when asked. The picture breaks on enforcement: anyone can tear an envelope open, and how firmly a memento stays sealed depends on the language.
Memento is one of eleven behavioural patterns, the family concerned with which object does which part of the work, and how objects communicate.
| Pattern | What it does |
|---|---|
| Chain of Responsibility | Passes a request along a chain of handlers until one handles it. |
| Command | Turns a request into an object that can be stored, queued or undone. |
| Interpreter | Represents a small language's grammar as classes and evaluates its sentences. |
| Iterator | Visits the elements of a collection without exposing how it is stored. |
| Mediator | Routes the communication between objects through one central object. |
| Memento (this topic) | Captures an object's state so it can be restored later. |
| Observer | Notifies many objects when one object changes. |
| State | Changes an object's behaviour when its internal state changes. |
| Strategy | Swaps one algorithm for another behind a common interface. |
| Template Method | Fixes an algorithm's steps in a base class and lets subclasses fill some in. |
| Visitor | Adds operations to a class hierarchy without changing its classes. |
Use it when
- An object must be restored to an earlier state, for undo, a checkpoint, or a rollback after a failed operation.
- Exposing the state through public fields or getters would let other code change it.
- The state is small enough, or changes rarely enough, to copy whole.
Avoid it when
- Each change can be reversed by a command that knows its inverse, which stores far less.
- The state is large and changes constantly, unless snapshots are capped or store only the difference.
- The state includes things that cannot be copied back, such as an open network connection or a sent email.
← → move through sections and cards