Memento is a behavioural design pattern that without violating encapsulation, allows object to capture and save its internal state so it can later be restored to this state (undo).
Applicability
- When you need to implement undo and redo functionality in your application.
- When you want to provide a way for user to save their progress in an application or game.
- You want to revert to an object’s original state if unexpected event happens. (especially in transaction systems to revert the transaction to its original state if transaction fails)
Approach
- Create Originator class that holds the state you want to capture and restore.
- Define the Memento class that stores a snapshot of the Originator’s state.
- Create caretaker class for storing and managing Memento objects. It can provide methods to save Mementos and retrieve them when needed.
Components
- Originator
- The Originator is the object whose internal state needs to be saved and restored
- It creates a memento containing a snapshot of its current internal state
- It uses a memento object to restore its state
- Memento
- The memento acts as a snapshot of the Originator’s state
- It stores the internal state of the Originator object. It may store as much or as little of Originator’s internal state as necessary.
- It has methods to get and set the state or relevant parts of the state, but it does not directly expose the state to other objects.
- It can either implemented as an inner class of the Originator or as an external class.
- Caretaker
- Responsible for capturing and restoring Originator state.
- Holds a collection of Mementos, which can be used to save and retrieve history states of the Originator.
- The caretaker does not modify (Memento is immutable) the Memento objects but acts as a repository for them.
Example
Identify memento pattern components
Originator: TextArea
Memento: Memento
Caretaker: TextEditor
Originator
We want to store the content of the TextArea
, it can create Memento objects to save the current content and restore it if needed.
Memento
The memento here is in a form of an inner class of the Originator. Its methods have private access modifier which enforces the encapsulation that no other class than TextArea
can have direct access to its snapshot, if the client wants to retrieve the snapshot it has to access it via the TextArea
’s public methods (save()
, restore()
).
class TextArea {
private String content;
public setContent(String content) {
this.content = content;
}
public String getContent() {
return content;
}
// create a Memento object to save the current state (snapshot)
public Memento save() {
return new Memento(contentToSave);
}
// restore the state from a Memento object
public void restore(Memento memento) {
this.content = memento.getSavedContent();
}
// inner Memento class - represents the snapshot of the TextArea
public static class Memento {
// the Memento data should be immutable
private final String savedContent;
// private Memento methods to enforce encapsulation
private Memento(String contentToSave) {
savedContent = contentToSave;
}
private String getSavedContent() {
return savedContent;
}
}
}
Caretaker
The caretaker class responsible for storing and managing Memento objects.
class TextEditor {
// stores a list of memento objects
private final Deque<TextEditor.Memento> historyState;
private TextArea textArea;
public TextEditorHisotry() {
historyState = new LikedList<>();
textArea = new TextArea();
}
public void write(String content) {
textArea.setContent(content);
// save the current state and store it to history
historyState.add(textEditor.save());
}
public void undo() {
// undo with the most recent history
textArea.restore(historyState.pop());
}
// roll back to a specific history version
public void revert(int index) {
textArea.restore(historyState.remove(index));
}
}
Client
The client creates instances of Originator and Caretaker class, it saves and restores the state of the TextArea
using Memento objects.
public class MementoPatternExample {
public static void main(String[] args) {
TextEditor editor = new TextEditor();
editor.write("Some text");
editor.write("Some more text");
editor.write("Even more text");
editor.undo();
}
Back to super node: Behavioural Patterns
Design_Pattern Behavioural_Design_Patterns SOFT2201 Memento_pattern