Behavioral Design Pattern · Java

Memento Design Pattern in Java

Capture an object’s state so it can be restored later without exposing its internal details.

What is Memento?

The Memento pattern allows an object’s internal state to be captured and restored later without breaking encapsulation. It is especially useful for undo features and restoring an object to an earlier state. In a text editor, the editor is the Originator, a memento stores a snapshot of the text, and a Caretaker manages the saved snapshots.

Beginner-friendly Java example

Focus on the roles in the example first. The pattern becomes easier when you can identify the sender, receiver, context, state, or strategy involved.

// Step 1: Define the Memento
class TextEditorMemento {
    private String text;

    public TextEditorMemento(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }
}

// Step 2: Define the Originator
class TextEditor {
    private String text;

    public void setText(String text) {
        this.text = text;
    }

    public TextEditorMemento save() {
        return new TextEditorMemento(text);
    }

    public void restore(TextEditorMemento memento) {
        this.text = memento.getText();
    }

    public void printText() {
        System.out.println("Current Text: " + text);
    }
}

// Step 3: Define the Caretaker
import java.util.Stack;

class TextEditorHistory {
    private Stack<TextEditorMemento> history = new Stack<>();

    public void save(TextEditorMemento memento) {
        history.push(memento);
    }

    public TextEditorMemento undo() {
        if (!history.isEmpty()) {
            return history.pop();
        }
        return null;
    }
}

// Step 4: Test the implementation
public class Main {
    public static void main(String[] args) {
        TextEditor textEditor = new TextEditor();
        TextEditorHistory history = new TextEditorHistory();

        textEditor.setText("Hello World!");
        textEditor.printText();

        // Save the current state before changing the text
        history.save(textEditor.save());
        textEditor.setText("Updated Text");
        textEditor.printText();

        // Undo and restore the saved state
        TextEditorMemento memento = history.undo();
        if (memento != null) {
            textEditor.restore(memento);
        }
        textEditor.printText();
    }
}

Benefits and trade-offs

Benefits
  • Keeps responsibilities focused.
  • Reduces conditional and tightly coupled code.
  • Makes behavior easier to extend and test.
Trade-offs
  • Can introduce extra objects and interfaces.
  • Too many small classes can make simple logic harder to follow.

Real-time use cases

  • Text editor undo and redo
  • Form draft recovery
  • Game checkpoints
  • Transaction rollback
  • Database restore points
Key takeawayCapture an object’s state so it can be restored later without exposing its internal details. Use it when behavior or communication is changing faster than the objects themselves.