🧩 Memento Pattern
✅ Intent
- Save and restore an object's internal state without exposing its internal structure
- Provide the ability to undo or rollback to a previous state
✅ Motivation
- Useful when you want to save a snapshot of the system at a specific moment
- Designed for full-state restoration, not just inverse actions
✅ When to Use
- Form inputs, save features in games, autosave systems in editors
- When state management is critical and you need reversible transitions
✅ Code Example
- TypeScript
- PHP
- Python
// Memento
class EditorMemento {
constructor(private readonly state: string) {}
getState(): string {
return this.state;
}
}
// Originator(状態を持つ)
class TextEditor {
private content = "";
type(text: string): void {
this.content += text;
}
getContent(): string {
return this.content;
}
createMemento(): EditorMemento {
return new EditorMemento(this.content);
}
restore(memento: EditorMemento): void {
this.content = memento.getState();
}
}
// Caretaker(履歴管理)
const editor = new TextEditor();
const history: EditorMemento[] = [];
editor.type("Hello ");
history.push(editor.createMemento());
editor.type("World");
history.push(editor.createMemento());
console.log(editor.getContent()); // Hello World
// Undo
history.pop(); // 現在の状態は捨てる
const last = history[history.length - 1];
editor.restore(last);
console.log(editor.getContent()); // Hello
<?php
class EditorMemento {
public function __construct(private string $state) {}
public function getState(): string {
return $this->state;
}
}
class TextEditor {
private string $content = "";
public function type(string $text): void {
$this->content .= $text;
}
public function getContent(): string {
return $this->content;
}
public function createMemento(): EditorMemento {
return new EditorMemento($this->content);
}
public function restore(EditorMemento $memento): void {
$this->content = $memento->getState();
}
}
// 利用例
$editor = new TextEditor();
$history = [];
$editor->type("Hello ");
$history[] = $editor->createMemento();
$editor->type("World");
$history[] = $editor->createMemento();
echo $editor->getContent() . "\n"; // Hello World
// Undo
array_pop($history); // 現在の状態を削除
$last = end($history);
$editor->restore($last);
echo $editor->getContent() . "\n"; // Hello
class EditorMemento:
def __init__(self, state: str):
self._state = state
def get_state(self) -> str:
return self._state
class TextEditor:
def __init__(self):
self._content = ""
def type(self, text: str):
self._content += text
def get_content(self) -> str:
return self._content
def create_memento(self) -> EditorMemento:
return EditorMemento(self._content)
def restore(self, memento: EditorMemento):
self._content = memento.get_state()
# 利用例
editor = TextEditor()
history: list[EditorMemento] = []
editor.type("Hello ")
history.append(editor.create_memento())
editor.type("World")
history.append(editor.create_memento())
print(editor.get_content()) # Hello World
# Undo
history.pop() # 最新の状態を破棄
last = history[-1]
editor.restore(last)
print(editor.get_content()) # Hello
✅ Explanation
This code uses the Memento
pattern to save and restore the state of a text editor.
The TextEditor
(originator) creates EditorMemento
(mementos) to store its state and uses them to restore past content.
1. Overview of the Memento Pattern
-
Memento: Stores the internal state of the originator
- Here:
EditorMemento
- Here:
-
Originator: Creates and restores mementos
- Here:
TextEditor
- Here:
-
Caretaker: Manages the history of mementos
- Here: A
history
list holds the saved mementos
- Here: A
2. Key Classes and Their Roles
-
EditorMemento
- Holds a snapshot of the editor’s content
- Exposes a
getState()
method for recovery
-
TextEditor
- Originator that maintains current text
- Has
createMemento()
to save state andrestore(memento)
to revert
-
Caretaker
- Stores the mementos and handles when to save/restore
- Here, the
history
array manages this role
3. UML Class Diagram
4. Benefits of the Memento Pattern
- State Preservation: Saves and restores internal state without exposing implementation details
- Encapsulation Friendly: Originator's internal data remains hidden from external classes
- History Management: Enables clean implementation of undo/redo systems
This pattern is ideal when you need to capture full snapshots of an object's state and revert to previous versions.
It is particularly useful in applications like form editors, games, and any situation where rollback is critical.