0
1

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が必要か?

❌ 状態をグローバル変数やdictなどでベタ保存

backup = {
    "text": editor.text,
    "cursor": editor.cursor
}

カプセル化を破壊し、変更に弱い構造


✅ 状態をMementoとしてオブジェクト化・隠蔽して記録

snapshot = editor.save()
...
editor.restore(snapshot)

内部状態を安全に保持し、構造的に復元可能


2. 基本構造

✅ Originator(状態を持つオブジェクト)

class Editor:
    def __init__(self):
        self._text = ""
        self._cursor = 0

    def write(self, text):
        self._text += text
        self._cursor = len(self._text)

    def save(self):
        return Memento(self._text, self._cursor)

    def restore(self, memento):
        self._text = memento.text
        self._cursor = memento.cursor

    def show(self):
        print(f"[Editor] '{self._text}' | cursor at {self._cursor}")

✅ Memento(状態を保存するクラス)

class Memento:
    def __init__(self, text, cursor):
        self.text = text
        self.cursor = cursor

✅ Caretaker(履歴管理者)

class History:
    def __init__(self):
        self._snapshots = []

    def backup(self, memento):
        self._snapshots.append(memento)

    def undo(self):
        if self._snapshots:
            return self._snapshots.pop()
        return None

✅ 使用例

editor = Editor()
history = History()

editor.write("Hello")
history.backup(editor.save())

editor.write(", World!")
editor.show()  # Hello, World!

editor.restore(history.undo())
editor.show()  # Hello

出力:

[Editor] 'Hello, World!' | cursor at 13
[Editor] 'Hello' | cursor at 5

3. Python的応用:Mementoをdeepcopyで代用する実用例

import copy

history = []
editor = Editor()

editor.write("A")
history.append(copy.deepcopy(editor))

editor.write("B")
history.append(copy.deepcopy(editor))

editor = history[-2]
editor.show()  # A

小規模アプリなら deepcopy によるスナップショットでも有効


4. 実務ユースケース

✅ Undo/Redo 機能の実装(エディタ、フォーム、設定画面)

→ 操作の履歴を構造化された状態で保持し、任意のタイミングで戻す


✅ 安全なロールバック処理(DB/設定変更/ユーザー操作)

→ 設定前の状態を保持しておき、異常時に復元可能


✅ オブジェクトの一時的スナップショット保存

テストや一時保存、比較検証などに活用


✅ タイムトラベル型UIの実装

→ アプリケーションの状態遷移を時間軸で記録・再生


5. よくある誤用と対策

❌ Mementoが内部構造を公開してしまう

→ ✅ 読み取り専用属性とし、直接操作を避ける


❌ 状態復元の副作用が大きすぎる

→ ✅ 復元時の処理が明確に定義されていることを保証


❌ 履歴管理(Caretaker)が肥大化・不整合

→ ✅ 履歴の最大数、メモリ制限、整合性検証を事前に設計


結語

Mementoパターンとは、“過去の状態を密やかに封じ込め、未来の柔軟性を担保する設計”である。

  • オブジェクトの内部状態を安全・構造的に保存・復元可能
  • Undo/Redo、ロールバック、履歴管理など、時系列的状態制御の基盤を提供
  • Pythonではクラスの柔軟性と動的属性によって、直感的かつ安全にMementoが構築可能

Pythonicとは、“状態の変化を設計的に制御すること”。
Mementoパターンはその制御を、スナップショットという静かな記憶に委ねる技法である。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?