2
3

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

❌ 状態変更が破壊的で戻せない設計

editor.text = "New text"
# 元の状態は失われる

→ 状態を戻す手段がないと、修正の追跡や巻き戻しが不可能


✅ 状態のスナップショットを保持し、必要に応じて復元

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._text = ""

    def type(self, words):
        self._text += words

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

    def restore(self, memento: Memento):
        self._text = memento.get_state()

    def show(self):
        print(self._text)

✅ Caretaker(Mementoを管理)

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

    def push(self, memento: Memento):
        self._undo_stack.append(memento)

    def pop(self):
        return self._undo_stack.pop() if self._undo_stack else None

✅ 使用例

editor = Editor()
history = History()

editor.type("Hello, ")
history.push(editor.save())

editor.type("world!")
editor.show()  # Hello, world!

editor.restore(history.pop())
editor.show()  # Hello,

3. Python的応用:DeepCopyによる簡易スナップショット

import copy

state = {"text": "initial", "cursor": 0}
snapshots = []

snapshots.append(copy.deepcopy(state))
state["text"] = "edited"
state["cursor"] = 6

state = snapshots[-1]
print(state)  # {'text': 'initial', 'cursor': 0}

辞書やデータ構造をそのまま保存・復元できる構成


4. 実務ユースケース

✅ テキストエディタのUndo/Redo機構

→ 編集前の状態をMementoとして記録し、任意のタイミングで巻き戻し


✅ フォーム入力のチェックポイント保存

→ 入力値の途中保存やエラー前の状態復元


✅ ゲームのセーブ/ロード設計

→ キャラクターの状態、アイテム、進行状況の保存と復元


✅ 設定画面や履歴の差し戻し機構

→ ユーザーが設定を戻したい場合に対応


5. よくある誤用と対策

❌ Mementoが内部状態に直接アクセス可能

→ ✅ get_state()restore() を通じて、カプセル化を維持


❌ スナップショットの保存タイミングが曖昧

→ ✅ 状態の変化直前に 明示的に save() を呼び出す


❌ Caretakerが状態に干渉する設計

→ ✅ Caretakerは Mementoの管理のみに専念し、状態の評価・変更は行わない


結語

Mementoパターンとは、“変化するものに過去を与え、未来を制御可能にする構造設計”である。

  • オブジェクトの状態を外部からアクセス不能な形で安全に退避
  • 「巻き戻し」や「途中保存」などの機能に、最適なスナップショット機構を提供
  • Pythonにおいては、オブジェクト指向とシリアライズ/deepcopyと組み合わせることで、直感的かつ堅牢な実装が可能

Pythonicとは、“状態を信頼できる形で記録・復元する”ことであり、
Mementoパターンはその過去との対話を、設計の一部として優雅に取り入れるための技法である。

2
3
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
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?