The Memento design pattern is a behavioral design pattern that allows you to save and restore an object’s internal state without violating encapsulation. It’s particularly useful when you need to implement undo mechanisms or save snapshots of an object’s state.

The pattern suggests that we use a special object (i.e., Memento) to store the snapshot of the original object’s (i.e., Originator) state . The Memento objects are made immutable by having only the getter and no setter methods. Creating these objects is delegated to the Originator object, ensuring no other object can access its internal private state. Finally, we use an external object (i.e., Caretakers) to store Memento objects created by the Originator.

Structure

The Memento pattern consists of the following key components:

  • Originator: is the object whose state is required to be saved and restored. Originator can save its current state in a Memento and also restore its state from a Memento
  • Memento: is an object that stores the snapshot for the internal state of the Originator. The Memento’s state is immutable and can only be accessed by the Originator which generated it
  • Caretaker: is responsible for managing multiple Memento’s for an object

When to use the Memento Pattern?

  • When you want to be able to take snapshots of an object’s internal state and restore it when needed
  • When you want a separate object to manage the snapshots instead of the one that generated them (Single Responsibility Principle)

Implementation Example

The code below demonstrates the Memento design pattern for a simple text editor application in Java. The TextEditor class (Originator) manages the current text state and can create TextEditorMemento objects to save its state. The TextEditorMemento class (Memento) stores a snapshot of the text editor’s state. The TextEditorHistory class (Caretaker) maintains a stack of mementos, allowing for undo operations. In the Solution class, we create a text editor, add text in stages, save states, and then demonstrate the ability to restore previous states using the saved mementos.

import java.util.Stack;

// Client class
public class Solution {
    
    public static void main(String[] args) {
        
        TextEditor editor = new TextEditor();
        TextEditorHistory history = new TextEditorHistory();

        editor.addText("Hello, ");
        history.push(editor.save());

        editor.addText("world!");
        history.push(editor.save());

        editor.addText(" How are you?");

        editor.restore(history.pop());
        System.out.println("After first restore: " + editor.getCurrentText());

        editor.restore(history.pop());
        System.out.println("After second undo: " + editor.getCurrentText());

    }
}

// Memento class
class TextEditorMemento {

    private final String text;

    public TextEditorMemento(String text) {

        this.text = text;
    }

    public String getText() {

        return text;
    }
}

// Originator class
class TextEditor {

    private StringBuilder currentText;


    public TextEditor() {

        this.currentText = new StringBuilder();
    }

    public void addText(String text) {

        currentText.append(text);
        System.out.println("Current State: " + currentText);
    }

    public String getCurrentText() {

        return currentText.toString();
    }

    public TextEditorMemento save() {

        System.out.println("Saving State...\n");
        return new TextEditorMemento(currentText.toString());
    }

    public void restore(TextEditorMemento memento) {

        System.out.println("\nRestoring State...");
        this.currentText = new StringBuilder(memento.getText());
    }
}

// Caretaker class
class TextEditorHistory {

    private final Stack<TextEditorMemento> history = new Stack<>();

    public void push(TextEditorMemento memento) {

        history.push(memento);
    }

    public TextEditorMemento pop() {

        if (!history.isEmpty()) {
            return history.pop();
        }

        return null;
    }
}

The output of the following program will be:

Current State: Hello, 
Saving State...

Current State: Hello, world!
Saving State...

Current State: Hello, world! How are you?

Restoring State...
After first restore: Hello, world!

Restoring State...
After second undo: Hello,