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)