SwadhyAI Notes

All Low-Level Design notes

Behavioral · Gang of Four

Memento

Memento is a behavioral pattern for saving and restoring internal state without exposing private fields. The originator creates a sealed snapshot; the caretaker stores snapshots and never peeks inside.

Example: an editor has private text, a cursor, and a selection. Undo should not mean getText() for the whole world — then every toolbar can poke the insides. The editor creates a sealed only it can read. The undo stack holds those snapshots.

How to explain this in an interview

  • Chess move with a clear inverse: Command. Castling / en passant mess: Board.save() first.
  • Editor keystrokes: Memento. Do not invert every character as a command.
  • Public getters on the snapshot mean you shipped a DTO, not a memento.
  • Bound the stack. Snapshots cost memory; say that if the document is huge.

Originator

Editor / Board

Creates and applies. The only type allowed to read the .

Memento

Sealed envelope

Nested class, private fields. to everyone but the originator.

Caretaker

History stack

The pushes and pops. It never calls getText().

Command vs Memento

Store the verb, or store the picture?

Command stores an action. Memento stores a picture of state. Undo a chess move with Command when PlayMove can invert: put the piece back. Undo an editor with Memento when inverting every keystroke is silly: restore the last picture. Combining them is normal — execute takes a memento first, undo restores it — but they answer different questions.

QuestionCommandMemento
What is stored?The verb + enough to reverseA sealed picture of fields
Who knows internals?Nobody — public API of the receiverOnly the originator
Chess undoPlayMove.undo() if inverse is clearrestore(snapshot) if reversing is a mess
Editor undoUsually the wrong toolThe default: save before type()

If you find yourself copying private fields in the command, you wanted a memento the originator created. See encapsulation.

Java: undo without getters for every field

History cannot read m.text. Nested Memento keeps the fields private. That is the whole trick, in Java.

java
class Editor {
  private String text = "";
  private int cursor = 0;

  Memento save() {
    return new Memento(text, cursor);
  }

  void restore(Memento m) {
    this.text = m.text;
    this.cursor = m.cursor;
  }

  void type(String s) {
    text = text.substring(0, cursor) + s + text.substring(cursor);
    cursor += s.length();
  }

  static final class Memento {
    private final String text;
    private final int cursor;
    private Memento(String text, int cursor) {
      this.text = text;
      this.cursor = cursor;
    }
  }
}

class History {
  private final Deque<Editor.Memento> stack = new ArrayDeque<>();
  void push(Editor.Memento m) { stack.push(m); }
  Editor.Memento pop() { return stack.pop(); }
  // History cannot read m.text — the fields are private to Editor.
}

Snapshots cost memory

For a board, a copy of the grid is fine. For a huge document, diffs are an optimization, not a different pattern. Bound the stack. Do not keep every keystroke forever in a machine-coding round unless they ask.

Combine without mixing jobs

execute() may call editor.save() and push the memento. undo() restores. The command still does not open the envelope. The originator still does not know about the stack.

A memento with public getters

If anyone can call memento.getText(), you did not protect the insides. You published a DTO.

Undo by poking private fields

command.board.grid = oldGrid is not Memento and not encapsulation. Reverse through the API, or let the board save and restore a snapshot it owns.

Save before mutate

The caretaker’s rule: push a snapshot, then change the originator. Undo pops and restore. Redo is a second stack of mementos, not a flag on Editor. History still cannot read fields.

1 · save

Editor.save() returns an opaque Memento.

2 · type

Editor.type mutates text and cursor.

3 · restore

History.pop() → Editor.restore(m).

Java: command that does not open the envelope

Combining patterns: the command holds a memento. It still does not read text. Chess uses this when PlayMove cannot invert castling.

java
class TypeText implements EditCommand {
  private final Editor editor;
  private final String chunk;
  private Editor.Memento before;

  public void execute() {
    before = editor.save();
    editor.type(chunk);
  }

  public void undo() {
    editor.restore(before);
  }
}

Checkpoints vs keystroke undo

A game save is a named memento. An editor undo stack is many small ones. Same pattern, different caretaker policy. Cap the undo stack unless the interviewer asks for unlimited history.

Package-private is not a leak

Nested private fields are the Java idiom. A public record Memento(String text, int cursor) is a DTO. Do not ship that as “Memento.”

How to explain this in an interview

“History holds snapshots it cannot read. Editor.save / restore is the only API.” If undo is ‘put the piece back,’ that is Command. If undo is ‘the board looked like this,’ that is Memento. Public getters on the snapshot mean you shipped a DTO.

Nearby in LLD