design·lab

Real-world combination

Undo/Redo = Command + Memento

Command turns each action into an object with execute()/undo(); Memento lets it snapshot exact state to restore — together they give clean, multi-level undo/redo.

✗ Problem

One state slot can't do multi-level undo

A naive editor keeps a single lastState. It remembers exactly one step back — no stack, no redo, and every action needs a hand-written inverse.

class Editor {
  lastState = null;

  type(s) {
    this.lastState = this.text;   // only ONE slot
    this.text += s;
  }

  undo() {
    this.text = this.lastState;   // 2nd undo? redo? ✗
  }
}
One variable = one step of history. Re-deriving each action's inverse by hand is error-prone and doesn't scale to redo.
✓ The combination

Two patterns, one job each

Command wraps each action as an object with execute()/undo(); Memento is the snapshot it captures so undo restores state exactly — no manual inverse logic.

class Command {
  execute(editor) {
    this.before = editor.snapshot();  // Memento
    this.mutate(editor.state);
    this.after = editor.snapshot();
  }
  undo(editor) { editor.restore(this.before); }
  redo(editor) { editor.restore(this.after); }
}

// Invoker
undoStack.push(cmd);
redoStack = [];  // new action clears redo
Invoker
undo/redo stacks
Command
execute() / undo()
Memento
snapshot
↑ state
Editor
originator
✓ See it live

Type, bold, clear — then rewind

Each action pushes a Command onto the undo stack, snapshotting state first. Undo pops it back onto redo; redo replays its captured "after" state.

(empty)
Undo stack
Redo stack
undo:0 · redo:0
✓ Takeaway

Why two patterns beat one

  • Multi-level undo/redo falls out for free — it's just push/pop on two stacks of commands.
  • Command gives every action a uniform execute()/undo() shape the invoker can queue, log, or replay.
  • Memento guarantees undo restores the exact prior state, no hand-written inverse math needed.
  • Real uses: text editors, Photoshop's history panel, IDE undo, form wizards with "back".
🎯 Combines: Command (encapsulate + reverse each action) + Memento (restore exact prior state), coordinated by an invoker holding undo/redo stacks.