2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで実装するMementoパターン:状態のスナップショットを安全に保存・復元する

Posted at

概要

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パターンはその自由な復元性を、構造の中に安全に埋め込む技法である。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?