Behavioral · DWG NO. 021

Memento

Capture and restore an object's internal state, without exposing that state to the outside world.

TypeBehavioral
ScopeSingle object's state
ComplexityLow–Medium
Common inUndo history, save/checkpoint systems, form drafts

Undo needs the old state, but nobody outside should be able to poke at it

Implementing undo naively often means exposing an object's internal fields publicly so something else can copy and later restore them — which also means anything else can now freely mutate that internal state, breaking the object's own invariants.

The object makes its own snapshots

The originator creates a memento — an opaque snapshot object — of its own state and can restore from one later. A separate caretaker (like a history stack) stores mementos but never looks inside them or modifies them directly.

Editor(originator)save()restore()Memento(opaque)History(caretaker)

An editor with undo via opaque snapshots

`History` stores mementos but never reads their contents — only `Editor` knows how to create or apply them.

editor-memento.js
class Editor {
  #text = "";

  type(str) { this.#text += str; }
  get content() { return this.#text; }

  save() {
    return { restore: (target) => { target.#text = this.#text; } };
    // returns an opaque memento closing over the current state
  }
}

class History {
  #snapshots = [];
  push(memento) { this.#snapshots.push(memento); }
  undo(editor) { this.#snapshots.pop()?.restore(editor); }
}

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

editor.type("Hello");
history.push(editor.save());
editor.type(", world");
console.log(editor.content); // "Hello, world"

history.undo(editor);
console.log(editor.content); // "Hello"

Trade-offs