🧩 Memento パターン
✅ 設計意図
- オブジェクトの状態(スナップショット)を保存しておき、後で復元できるようにする
- 外部から状態にアクセスせず、内部状態をそのまま記録
✅ 適用理由
- 特定のタイミングで状態を保存 → 戻す
- 完全な復元を目的とする場合に向いている
✅ 向いているシーン
- フォームの一括入力、ゲームのセーブ機能、ドキュメントの自動保存など
✅ コード例
- 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
✅ 解説
このコードは Memento
パターン を使用して、TextEditor
の状態を保存し、後でその状態に戻す(Undo
)機能を実現している。
Memento
パターンは、オブジェクトの内部状態を保存し、後でその状態を復元できるようにするデザインパターン。
1. Memento パターンの概要
- Memento: 保存される状態を表現するクラス
- このコードでは
EditorMemento
が該当
- このコードでは
- Originator: 状態を持ち、
Memento
を作成・復元するクラス- このコードでは
TextEditor
が該当
- このコードでは
- Caretaker:
Memento
を管理し、必要に応じてOriginator
に渡すクラス(またはコード)- このコードでは
history
配列が該当
- このコードでは
2. 主なクラスとその役割
EditorMemento
Memento
クラスTextEditor
の状態を保存し、その状態を取得するためのgetState
メソッドを提供
TextEditor
Originator
クラス- 現在の状態を保持し、
createMemento
メソッドで状態を保存 restore
メソッドでMemento
を使用して状態を復元
Caretaker
Memento
を管理する役割を持つ- このコードでは
history
配列がその役割を果たし、状態の履歴を保存・管理
3. UML クラス図
4. Memento パターンの利点
- 状態の保存と復元: オブジェクトの状態を簡単に保存・復元可能
- カプセル化の維持:
Memento
によってOriginator
の内部状態が外部に漏れない - 履歴管理:
Caretaker
を使用して状態の履歴を管理可能
この設計は、オブジェクトの状態を保存して後で復元する必要がある場面で非常に有効であり、Undo/Redo
機能を実現する際に役立つ。