0
0

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.content = backup_content  # 外部で直接触るとリスク大

内部構造を外部に晒すことで、再現性や安全性が崩れる


✅ 状態を「メメント」として保存・復元し、情報隠蔽を維持

memento = editor.save()
editor.restore(memento)

安全にスナップショットを取り、状態を巻き戻せる


2. 基本構造

✅ Memento(スナップショット)

class Memento:
    def __init__(self, state: str):
        self._state = state

    def get_state(self):
        return self._state

✅ Originator(状態を持つ本体)

class Editor:
    def __init__(self):
        self._content = ""

    def write(self, text):
        self._content += text

    def show(self):
        print(f"[現在の内容] {self._content}")

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

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

✅ Caretaker(メメントの管理)

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

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

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

✅ 使用例

editor = Editor()
history = History()

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

editor.write("world!")
editor.show()  # [現在の内容] Hello, world!

editor.restore(history.pop())
editor.show()  # [現在の内容] Hello, 

出力:

[現在の内容] Hello, world!  
[現在の内容] Hello, 

3. Python的応用:copy.deepcopy で一時保存としてのMementoを表現

import copy

class MementoStyleList(list):
    def snapshot(self):
        return copy.deepcopy(self)

    def restore(self, snapshot):
        self.clear()
        self.extend(snapshot)

状態が複雑でもdeepcopyを使えば簡易Mementoが可能


4. 実務ユースケース

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

→ 各入力・操作に対してスナップショットを記録


✅ ゲームのセーブ・ロード機能

→ 現在のキャラクター状態や進行状況を安全に保存・復元


✅ フォーム入力の復元、履歴管理

→ 入力ミスやリセットに対して巻き戻し可能な履歴


✅ 設定変更前のロールバック

→ 設定適用前の状態を保持し、問題があれば元に戻す


5. よくある誤用と対策

❌ 状態が漏れてカプセル化が破られている

→ ✅ Mementoの中身は原則として公開しない設計にする


❌ Mementoに副作用を含めてしまう

→ ✅ 純粋な状態のみを保存するよう設計し、振る舞いは持たせない


❌ Mementoのサイズが大きくなりすぎてメモリ効率が悪い

→ ✅ 差分保存(Diff)や圧縮・間引き記録などで軽量化を検討


結語

Mementoパターンとは、“時間を保存する設計”である。

  • 状態の保存と復元を安全に行い、情報隠蔽を保ったまま過去へ遡る機能を実現
  • 編集操作やシステム状態に対して、巻き戻し・やり直しの設計自由度を高める
  • Pythonでは、クラス・関数・コピー操作で柔軟かつ直感的に構築可能

Pythonicとは、“巻き戻せることを、設計によって自然に担保すること”。
Mementoパターンはその再現可能性を、構造に組み込む技法である。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?