Problem
The Memento pattern addresses the need to capture and restore an object's internal state without violating its encapsulation. This is useful in scenarios where you want to implement undo/redo functionality, allowing an object to revert to a previous state.
Solution
The Memento pattern involves three main components:
- Originator: The object whose internal state needs to be saved and restored.
- Memento: An object that stores the internal state of the originator. The memento is immutable.
- Caretaker: Responsible for requesting the originator to save or restore its state from a memento.
The originator creates a memento containing a snapshot of its current state. This memento can then be stored by the caretaker and used to restore the originator's state when needed.
Pros and Cons
Pros
- Preserves Encapsulation: Allows an object's internal state to be saved and restored without exposing its implementation details.
- Simple Undo/Redo: Facilitates the implementation of undo/redo functionality, making the system more robust and user-friendly.
- State History: Allows maintaining a history of previous states of the object, enabling navigation between different states.
Cons
- Memory Consumption: Storing multiple mementos can consume significant memory, especially if the object's state is large.
- Additional Complexity: Introduces additional complexity to the code, with the need to manage the creation and restoration of mementos.
- Caretaker Responsibility: The caretaker needs to manage mementos efficiently, which can add responsibility and complexity to the system.
Example of Real-World Application
A practical example of the Memento pattern is in text editors that offer undo/redo functionality. Each change to the document can be saved as a memento, allowing the user to revert to previous states of the document as needed.
Example Code in Java
Memento pattern in code:
// Originator
public class Editor {
private String content;
public void setContent(String content) {
this.content = content;
}
public String getContent() {
return content;
}
public Memento save() {
return new Memento(content);
}
public void restore(Memento memento) {
content = memento.getContent();
}
// Memento
public static class Memento {
private final String content;
public Memento(String content) {
this.content = content;
}
private String getContent() {
return content;
}
}
}
// Caretaker
public class History {
private final Stack<Editor.Memento> history = new Stack<>();
public void save(Editor editor) {
history.push(editor.save());
}
public void undo(Editor editor) {
if (!history.isEmpty()) {
editor.restore(history.pop());
}
}
}
// Client code
public class Client {
public static void main(String[] args) {
Editor editor = new Editor();
History history = new History();
editor.setContent("Version 1");
history.save(editor);
System.out.println(editor.getContent());
editor.setContent("Version 2");
history.save(editor);
System.out.println(editor.getContent());
editor.setContent("Version 3");
System.out.println(editor.getContent());
history.undo(editor);
System.out.println(editor.getContent());
history.undo(editor);
System.out.println(editor.getContent());
}
}
Top comments (0)