概要
Memento(メメント)パターンは、
オブジェクトの内部状態を保存し、後からその状態に戻す(復元する)ことを可能にする設計パターンである。
主にUndo / Redo の実装、状態の巻き戻し、トランザクション処理などに応用される。
**「状態の履歴を取っておきたいが、内部構造を晒したくない」**という要件に対して非常に有効。
1. なぜMementoが必要か?
❌ 状態復元のためにオブジェクトの内部構造に触れてしまう
state = editor.__dict__.copy() # 非公開な内部情報に依存
→ カプセル化が破られ、保守性・安全性が失われる
✅ 状態をMementoとして別オブジェクトに保存し、後から復元可能にする
snapshot = editor.save()
editor.restore(snapshot)
→ 外部から状態を安全に操作でき、履歴管理が明確になる
2. 基本構造
✅ Memento(スナップショット)
class Memento:
def __init__(self, content):
self._state = content
def get_state(self):
return self._state
✅ Originator(状態を持つオブジェクト)
class TextEditor:
def __init__(self):
self._content = ""
def write(self, text):
self._content += text
def save(self) -> Memento:
return Memento(self._content)
def restore(self, memento: Memento):
self._content = memento.get_state()
def show(self):
print(f"[Editor] 現在の内容: {self._content}")
✅ Caretaker(履歴管理)
class History:
def __init__(self):
self._history = []
def push(self, memento: Memento):
self._history.append(memento)
def pop(self) -> Memento:
return self._history.pop()
✅ 使用例
editor = TextEditor()
history = History()
editor.write("Hello, ")
history.push(editor.save())
editor.write("World!")
history.push(editor.save())
editor.show() # Hello, World!
editor.restore(history.pop())
editor.show() # Hello,
editor.restore(history.pop())
editor.show() # (空)
出力:
[Editor] 現在の内容: Hello, World!
[Editor] 現在の内容: Hello,
[Editor] 現在の内容:
3. Python的応用:デコレータによる自動スナップショット保存
def with_snapshot(method):
def wrapper(self, *args, **kwargs):
self._history.append(self.save())
return method(self, *args, **kwargs)
return wrapper
class AutoEditor(TextEditor):
def __init__(self):
super().__init__()
self._history = []
@with_snapshot
def write(self, text):
super().write(text)
def undo(self):
if self._history:
self.restore(self._history.pop())
→ 操作のたびに自動的に履歴を残す実装も可能
4. 実務ユースケース
✅ テキストエディタのUndo/Redo機能
→ 書き換えのたびに状態を保存し、任意の時点に戻す
✅ フォーム入力の一時保存・リセット
→ ユーザー操作を巻き戻す
✅ ゲームのセーブ/ロード機構
→ スナップショットで状態を完全に記録・復元
✅ データベースや処理のトランザクション管理
→ 状態変更前後でロールバック可能な安全性を確保
5. よくある誤用と対策
❌ Mementoがオブジェクトの内部構造をそのまま持ってしまう
→ ✅ 内部状態のみを保持し、必要な最低限の情報に留める
❌ Mementoの数が増えすぎてメモリを圧迫
→ ✅ 履歴数に制限を設ける/スナップショットの差分化も検討
❌ OriginatorとCaretakerの責任が曖昧
→ ✅ Originatorは状態保存・復元、Caretakerは履歴管理に専念する
結語
Mementoパターンとは、“状態を一瞬で保存し、未来でそれを復元できる設計”である。
- カプセル化を保ちつつ、状態の巻き戻しや履歴管理を構造的に実現
- Undo/Redoや状態遷移管理において、データと操作の分離を可能にする
- Pythonではクラスベースで明確に分離し、柔軟で直感的な状態管理が構築可能
Pythonicとは、“記録せずに戻るのではなく、戻れるように記録しておくこと”。
Mementoパターンはその記憶の知性を、設計の可逆性として定義する技法である。