Skip to content

Memento Pattern — Short Notes

Save and restore an object's state

Builds on Encapsulation

Stage 3advanced3 min read

Purpose Recap

The Memento Pattern lets an object save and restore its state without showing its internal data, so encapsulation (private data) is kept.

This suits features like Undo / Redo in text editors, games, and drawing tools.

Class Responsibilities (Overview)

1. TextEditor (Originator)

  • The object whose state is saved.
  • Knows how to create a snapshot (save()) and how to restore one (restore()).
  • Does not know who stores the snapshots.

2. EditorMemento (Memento)

  • Holds a snapshot of the editor’s state (here, the text content).
  • Immutable: once created, it cannot be changed (its content field is final).
  • Has a getter, getContent(), so the TextEditor can read the snapshot when it restores.

3. Caretaker

  • Keeps the history, a stack of mementos (last in, first out).
  • Handles saving and restoring states.
  • Does not change or read the internal data of TextEditor or EditorMemento.
  • Acts as the "history manager" for undo/redo.

4. TextEditorMain

  • Shows how to use the pattern.
  • Creates the editor and caretaker, saves states, changes the content, and undoes a change.

How It Works (Step-by-Step Flow)

  1. Initial State Creation
    editor.write("Hello World");
    caretaker.saveState(editor);
  • The editor writes some text.
  • saveState(editor) calls editor.save(), which creates a new EditorMemento containing "Hello World".
  • The caretaker pushes this snapshot onto its history stack.
  1. State Change

    editor.write("Hello Everyone");
    caretaker.saveState(editor);
    • The editor writes new content.
    • The caretaker saves this new state on the stack too. The stack now holds both snapshots.
  2. Undo Operation

    caretaker.undo(editor);
    • The caretaker pops the most recent snapshot ("Hello Everyone") off the stack. That is the current state, so it is dropped.
    • Then it calls editor.restore(history.peek()) with the snapshot now on top ("Hello World"). peek() reads the top without removing it.
    • Limit: if only one state is saved, pop() empties the stack and peek() throws EmptyStackException. The code only checks that the stack is not empty before the pop().
  3. Final Output

    System.out.println(editor.getContent());
    • Prints "Hello World". The undo reverted the last change.

How This Fixes the Old Code

Problem in Old CodeHow Good Code Fixes It
No way to store previous statesThe EditorMemento class now stores snapshots of each state.
TextEditor risked exposing internal dataSnapshots live inside EditorMemento, so the editor's data stays private.
Undo/Redo logic was missingThe Caretaker keeps the history in a stack and provides undo.
Violated SRP (Single Responsibility)TextEditor only edits text. Caretaker handles history. Each class has one job.

Key Advantages of This Design

  1. Encapsulation is preserved

    • The internal state of TextEditor stays hidden. Only the memento holds a copy.
  2. Easy to extend

    • Adding redo or multi-level undo is straightforward.
  3. SRP compliance

    • Each class has one concern: editing, storing a snapshot, or managing history.
  4. Reusability

    • The same Caretaker idea can be used for other objects that need history.

Summary

The improved code applies the Memento Pattern by giving each of three components its own job:

  • TextEditor → Originator
  • EditorMemento → Memento (state holder)
  • Caretaker → State manager (undo/redo handler)

This design gives you undo while keeping the internal state private. The code is also easy to maintain and extend. This fixes the problems in the old code.

In this topic

After code4 files

After/Caretaker.java20 linesGitHub
package DesignPatterns.BehaviouralPatterns.MementoPattern.After;import java.util.Stack;// Caretaker class: Manage Mementos (snapshots of the texteditor state)public class Caretaker {    private final Stack<EditorMemento> history = new Stack<>();    public void saveState(TextEditor editor) {        history.push(editor.save());    }    public void undo(TextEditor editor) {        if (!history.empty()) {            history.pop();            editor.restore(history.peek());        }    }}
After/EditorMemento.java15 linesGitHub
package DesignPatterns.BehaviouralPatterns.MementoPattern.After;// Mementor Class: Stores the internal state of the Text Editorpublic class EditorMemento {    private final String content;    public EditorMemento(String content) {        this.content = content;    }    public String getContent() {        return content;    }}
After/TextEditor.java24 linesGitHub
package DesignPatterns.BehaviouralPatterns.MementoPattern.After;public class TextEditor {    private String content;    public void write(String text) {        this.content = text;    }    // Save the current state of editor    public EditorMemento save() {        return new EditorMemento(content);    }    // Restore (Memento -> update the state of current content    public void restore(EditorMemento memento) {        content = memento.getContent();    }    public String getContent() {        return content;    }}
After/TextEditorMain.java22 linesGitHub
package DesignPatterns.BehaviouralPatterns.MementoPattern.After;public class TextEditorMain {    public static void main(String[] args) {        TextEditor editor = new TextEditor();        Caretaker caretaker = new Caretaker(); // History // State management        editor.write("Hello World");        caretaker.saveState(editor);        editor.write("Hello Everyone");        caretaker.saveState(editor);        // Undo the last write        caretaker.undo(editor);        System.out.println(            "Printing the current content : " + editor.getContent()        );    }}

Done with this topic?

How well do you know it?

PreviousSequential Request Processing