Design Patterns Memento

The Memento pattern captures an object's internal state in a snapshot and restores it later. Sealed snapshots keep outside code from peeking inside or breaking encapsulation. Undo features and save points rely on this idea.

The Real-World Analogy

A video game offers save slots. Players store progress before a tough level and reload it after a mistake. The save file holds everything needed to rebuild the moment, and the player never edits its contents by hand.

Problem Without Memento

Editor
  text = "Hello World"

Option A: expose every field so outside code can copy them
          → breaks encapsulation, any class can corrupt the editor

Option B: skip undo entirely
          → users lose work after every mistake

Solution With Memento

┌────────────┐  creates   ┌────────────┐  stored by  ┌────────────┐
│ Originator │ ─────────▶ │  Memento   │ ◀────────── │ Caretaker  │
│ (Editor)   │            │ (snapshot) │             │ (History)  │
│            │ ◀───────── │            │             │            │
└────────────┘  restores  └────────────┘             └────────────┘

Roles

  • Originator: the object whose state needs saving. It creates and reads snapshots.
  • Memento: the sealed snapshot. Only the originator opens it.
  • Caretaker: the keeper of snapshots. It stores them in order and never looks inside.

Undo Timeline

Type "A"   → save  ┌──────┐
Type "AB"  → save  │ "A"  │
Type "ABC" → save  │ "AB" │  history stack
                   │ "ABC"│
                   └──────┘
Undo → pop "ABC", restore "AB"
Undo → pop "AB", restore "A"

Code Example

class Editor {
    private String text = "";

    void type(String words) { text = text + words; }
    String getText() { return text; }

    Memento save() {
        return new Memento(text);          // snapshot
    }

    void restore(Memento m) {
        text = m.getState();               // rollback
    }

    static class Memento {
        private final String state;
        private Memento(String state) { this.state = state; }
        private String getState() { return state; }
    }
}

class History {
    private Stack snapshots = new Stack();
    void push(Editor.Memento m) { snapshots.push(m); }
    Editor.Memento pop() { return snapshots.pop(); }
}

Editor editor = new Editor();
History history = new History();

editor.type("Hello");
history.push(editor.save());
editor.type(" World");
history.push(editor.save());
editor.type("!!!");

editor.restore(history.pop());   // text becomes "Hello World"
editor.restore(history.pop());   // text becomes "Hello"

Design Choices

Full Snapshot

Stores the entire state each time. The approach is simple and memory-hungry.

Incremental Snapshot

Stores only the change since the last save. Memory use drops, and restore logic grows harder.

History Limit

Many applications keep only the latest 50 or 100 snapshots to cap memory.

Real Projects Using Memento

ScenarioSaved State
Text and image editorsContent and cursor position
Form wizardsAnswers from earlier steps
Game save pointsLevel, score, inventory
Database transactionsData before a risky change

Memento Versus Command

Command stores the action and its reverse. Memento stores the state itself. Large applications often combine both: commands describe what happened, and mementos guard against complex reversals.

Advantages and Disadvantages

AdvantagesDisadvantages
Undo without breaking encapsulationMany snapshots consume memory
Simple originator codeCaretaker must manage cleanup
Clear separation of dutiesLanguages without private access weaken the seal

Step-by-Step Walkthrough

Trace the code example. The editor receives "Hello", and the program saves a memento holding that text. More typing produces "Hello World", and a second memento joins the stack. A third edit adds "!!!" without a save.

The first pop returns the "Hello World" snapshot, and restore() rewrites the editor text. A second pop returns the "Hello" snapshot. Each restore leaves the stack one entry shorter.

Adding Redo

Undo needs a second stack for redo. Before restoring an older snapshot, the program saves the current state onto the redo stack. A redo request pops from the second stack. Any new edit clears the redo stack, because the old future no longer applies.

Common Mistakes

  • Saving mutable objects by reference. Copy the data into the memento.
  • Letting the caretaker read memento contents.
  • Saving on every keystroke without limits, which drains memory.

Plain-Words Summary

Memento helps most when saving state is cheap and mistakes are common. Drawing programs, text editors, and form wizards all benefit. Keep snapshots small by saving only the fields that matter, and cap the history length. Users rarely need a hundred undo steps, and a modest limit protects memory while delivering the comfort of a safety net.

Key Takeaways

  • A memento captures state without exposing internal details.
  • The originator creates and restores, and the caretaker only stores.
  • Limit history size to protect memory.
  • Pair Memento with Command for robust undo and redo.