Table of Contents
Introduction
The Memento pattern is a behavioral software design pattern. It is used to record, or memorize, the internal state of an object. The pattern makes an object store the internal state of another object. One of the most clear examples of this, is undo and redo in about any application, such as about any office application. The storage of the state can be achieved without violating encapsulation. The so called Memento object stores the internal state of the Originator object.
- Memento: A snapshot of the originator.
- Originator: The object that needs saved states.
- Caretaker: Manages memento objects.
Use Cases
- You want to implement Undo and Redo.
- You want to implement transactional rollbacks.
Pitfalls
- Potential high memory usage.
Java Example
To demonstrate the structure and workings of the memento design patter I have created a JTextArea that auto saves the state of the text area every so many seconds. For this reason, you can use the control + z key combination to undo and the control + r key combination to redo.
Main Class
The Main class does the following:
- Listen to key input.
- Instantiate the Originator which holds the TextArea and states of the TextArea.
- Instantiate the Caretaker which keeps track of the snapshots (Memento objects) which are states of the Originator.
- Instantiate the AutoSaveManager which automatically creates snapshots.
package com.chosengambit.designpatterns;
import com.chosengambit.memento.AutoSaveManager;
import com.chosengambit.memento.Caretaker;
import com.chosengambit.memento.Originator;
import java.awt.Component;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class Main implements KeyListener {
private static Originator originator;
private static Caretaker caretaker;
private static AutoSaveManager autoSaveManager;
public static void main(String[] args) {
try {
// UI components
JFrame frame = new JFrame("Text Editor");
JTextArea textArea = new JTextArea();
// Setup key listener
Main listener = new Main();
setupKeyListener(textArea, listener);
// Originator and Caretaker objects from Memento design pattern
originator = new Originator(frame, textArea);
caretaker = new Caretaker();
// Setup auto-save manager
autoSaveManager = new AutoSaveManager(originator, caretaker);
}
catch (Exception e) {
System.out.println(e.toString());
}
}
@Override
public void keyPressed(KeyEvent e) {
if (e.isControlDown()) {
if (e.getKeyCode() == KeyEvent.VK_R) {
originator.setState(caretaker.redo());
autoSaveManager.restartTimer();
}
else if (e.getKeyCode() == KeyEvent.VK_Z) {
originator.setState(caretaker.undo());
autoSaveManager.restartTimer();
}
}
}
private static void setupKeyListener(Component component, KeyListener listener) {
component.addKeyListener(listener);
}
@Override
public void keyReleased(KeyEvent e) {}
@Override
public void keyTyped(KeyEvent e) {}
}
JavaMemento Class
Very straightforward, our Memento class does save on thing of the state of the originator, which is the text inside the TextArea. This could be extended.
package com.chosengambit.memento;
public class Memento {
private final String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return this.state;
}
}
JavaOriginator Class
- Holds the TextArea and a state of the TextArea.
- Can return the state as a Memento object.
- Can load set the state which is a Memento object.
package com.chosengambit.memento;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class Originator {
private final JFrame frame;
private final JTextArea textArea;
public Originator(JFrame frame, JTextArea textArea) {
this.frame = frame;
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
this.textArea = textArea;
setupTextArea();
}
public void setState(Memento memento) {
if (memento != null)
this.textArea.setText(memento.getState());
}
public Memento getState() {
return new Memento(this.textArea.getText());
}
private void setupTextArea() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(640,480));
Container contentPane = frame.getContentPane();
contentPane.add(textArea);
frame.pack();
frame.setVisible(true);
}
}
JavaCaretaker Class
- Holds a List of Memento objects, which are saved states for the Originator.
- Implements undo and redo, which both return a saved state (Memento object).
- Can save a new state.
package com.chosengambit.memento;
import java.util.ArrayList;
import java.util.List;
public class Caretaker {
private int historyIndex = 0;
private final List<Memento> history = new ArrayList<>();
public Memento undo() {
historyIndex = --historyIndex < 0 ? 0 : historyIndex;
return loadState(historyIndex);
}
public Memento redo() {
historyIndex = ++historyIndex >= history.size() ? history.size()-1 : historyIndex;
return loadState(historyIndex);
}
private Memento loadState(int index) {
if (index >= 0 && index < history.size())
return history.get(index);
return null;
}
public void saveState(Memento snapshot) {
String current = snapshot.getState();
String last = !history.isEmpty() ? history.getLast().getState() : null;
if (last == null || !current.equals(last)) {
// trim future states
while (history.size() > historyIndex + 1) {
history.remove(history.size() - 1);
}
history.add(snapshot);
historyIndex = history.size()-1;
System.out.println("Perform auto-save ");
}
}
}
JavaAutoSaveManager Class
This class is not part of the pattern, but I made it to have a mechanism that creates new save states.
- Every 5 seconds a new save state is made.
- You can restart the auto save timer.
package com.chosengambit.memento;
import javax.swing.Timer;
public class AutoSaveManager {
private Timer saveTimer;
public AutoSaveManager(Originator originator, Caretaker caretaker) {
caretaker.saveState(new Memento(""));
this.saveTimer = new Timer(5 * 1000, (e) -> {
Memento snapshot = originator.getState();
caretaker.saveState(snapshot);
});
saveTimer.setRepeats(true);
saveTimer.start();
}
public void restartTimer() {
this.saveTimer.restart();
}
}
JavaClass Diagram

Conclusion
I tried to create a simple demonstration of the Memento design pattern, with an (oversimplified) auto-save mechanism. The Originator is the object that you want to keep track of states for. The Caretaker takes care of these states. You need an overarching/umbrella class to direct these objects. In our case, we had a AutoSaveManager automatically make snapshots at an interval.
References
Freeman, E., Bates, B., & Sierra, K. (2004). Head first design patterns.
Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software.
Wikipedia contributors. (2024). Software design pattern. Wikipedia. https://en.wikipedia.org/wiki/Software_design_pattern