概要
Memento(メメント)パターンは、
オブジェクトの内部状態をスナップショットとして記録・保存し、
その状態を後から安全に復元できるようにするための設計パターンである。
Undo/Redo、タイムトラベル、履歴管理などの実装に非常に適しており、
「内部状態のカプセル化を保持したまま復元する」ことが最大の特徴。
1. なぜMementoが必要か?
❌ 状態の変更に対応したUndo処理が複雑すぎる
# 状態の保存なしにロールバック不能
editor.content = "新しい内容"
→ 状態の復元を実現するには、状態スナップショットの保存が必要
✅ 状態を外部に記録し、任意のタイミングで復元可能に
snapshot = editor.save()
# ...
editor.restore(snapshot)
→ 内部構造に立ち入らず、安全に状態を復元可能にする
2. 基本構造
✅ Memento(スナップショット)
class Memento:
def __init__(self, state):
self._state = state
def get_state(self):
return self._state
✅ Originator(状態を持つ本体)
class Editor:
def __init__(self):
self._content = ""
def type(self, words):
self._content += words
def save(self):
return Memento(self._content)
def restore(self, memento):
self._content = memento.get_state()
def show(self):
print(f"内容: {self._content}")
✅ Caretaker(履歴の管理)
class History:
def __init__(self):
self._mementos = []
def push(self, memento):
self._mementos.append(memento)
def pop(self):
return self._mementos.pop() if self._mementos else None
✅ 使用例
editor = Editor()
history = History()
editor.type("Hello ")
history.push(editor.save())
editor.type("World!")
history.push(editor.save())
editor.show() # → 内容: Hello World!
# Undo
editor.restore(history.pop())
editor.show() # → 内容: Hello
# Undo again
editor.restore(history.pop())
editor.show() # → 内容:
3. Python的応用:deepcopyベースの汎用Memento実装
import copy
class GenericMemento:
def __init__(self, obj):
self._snapshot = copy.deepcopy(obj)
def restore(self):
return copy.deepcopy(self._snapshot)
→ どんなオブジェクトでも状態を保持・復元できる汎用ツールとして応用可能
4. 実務ユースケース
✅ テキストエディタのUndo/Redo機能
→ 入力内容を時系列で保存し、任意の時点へロールバック
✅ ゲームのセーブポイント・チェックポイント
→ キャラクターの状態やフィールド情報などを安全に巻き戻し
✅ データベーストランザクションのローカルロールバック
→ 書き込み前の状態を保持し、整合性のある巻き戻し
✅ スプレッドシート・フォームの編集履歴追跡
→ 入力状態を保持して、元の状態へ簡単に戻せる
5. よくある誤用と対策
❌ Mementoに処理ロジックを含めてしまう
→ ✅ Mementoは状態の保存・復元に限定すべき
❌ CaretakerがOriginatorの内部状態を操作する
→ ✅ Originatorだけが状態の保存・復元を行うべきであり、他者は介入不可
❌ Mementoの量が肥大化してパフォーマンスに影響
→ ✅ 定期保存・差分保存・容量制限などの設計的対処が必要
結語
Mementoパターンとは、“変化を記録し、過去へ戻るための設計的タイムマシン”である。
- 状態を外部に安全に保存し、任意のタイミングで復元可能にする構造
- Undo/Redo、履歴、復元処理をカプセル化と責務分離の原則に基づいて構築
- Pythonでは柔軟なオブジェクト操作と
deepcopy
の活用により、明快かつ強力な状態復元が可能
Pythonicとは、“変化を記録し、戻る自由を与える”こと。
Mementoパターンはその自由な復元性を、構造の中に安全に埋め込む技法である。