Python基礎 オブジェクト指向20(Memento) 振る舞いに関するデザインパターン
| 登録日 | :2026/01/28 18:35 |
|---|---|
| カテゴリ | :Python基礎 |
(オブジェクトの種類)
オブジェクトの現在の状態を保存しておき、状態が変化した場合でも、その時の状態に戻すことができるようにするパターン
- Cntl + Zの undo機能を実現する
- 状態を生成するクラスとその履歴を管理するクラスを分離する
構成要素
Originator
- 保存対象となるクラス
- 内部状態を保存するメソッドとリストアするメソッドを持つ
Memento
- Originatorオブジェクトを保存する記憶用クラス
ConcreteMemento
- Mementoを継承(実装)する子クラス
- 保存した状態を取得するメソッドを持つ
Caretaker
- Mementoオブジェクトを管理するクラス
- バックアップやUndo のメソッドを持つ
オブジェクト指向的要素
カプセル化の破壊を防ぐパタン
-
Mementoパターンを使わず内部状態の保存・復元をする場合、状態を公開する必要がある。
-
Originator自身が保存操作を行うことで、内部状態を非公開としたままスナップショットを作成する。
メリット・デメリット
メリット
- カプセル化の破壊することなく、オブジェクトの状態のスナップショットを作成・復元できる
- スナップショットの管理をCaretakerに任せることで、Originatorクラスをシンプルに保ことができる
デメリット
- Mementoを大量に作成してしまうとメモリ使用量が増加する。
使い所
スナップショットを作成したい場合
- Undo機能
- ゲームの保存
など
サンプル
メモ帳のUndo機能の例
from abc import ABC, abstractmethod
import datetime
from typing import List
class Memento(ABC):
@abstractmethod
def get_memo(self) -> str:
pass
class ConcreteMemento(Memento):
def __init__(self, memo:str):
self.__memo = memo
self.__date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def get_memo(self) -> str:
return self.__memo
def __str__(self):
return f"{self.__date} / ({self.get_memo()})"
class Notepad(object):
def __init__(self, memo:str):
self.__memo = memo
def get_memo(self) -> str:
return self.__memo
def add_memo(self, memo: str):
self.__memo = memo
def save(self) -> Memento:
print("save memo")
return ConcreteMemento(self.get_memo())
def restore(self, memento: Memento):
self.add_memo(memento.get_memo())
class Caretaker(object):
def __init__(self, notepad: Notepad, mementos: List[Memento] = []):
self.__notepad = notepad
self.__mementos = mementos
def backup(self):
self.__mementos.append(self.__notepad.save())
def undo(self):
if not len(self.__mementos):
print("There is no snapshot")
return
memento = self.__mementos.pop()
self.__notepad.restore(memento)
def show_history(self):
for memento in self.__mementos:
print(memento)
if __name__ == '__main__':
notepad = Notepad("first memo")
caretaker = Caretaker(notepad)
caretaker.backup
notepad.add_memo("second memo")
caretaker.backup()
notepad.add_memo("third memo")
caretaker.backup()
print(notepad.get_memo())
caretaker.show_history()
print("")
caretaker.undo()
print(notepad.get_memo())
print("")
caretaker.undo()
print(notepad.get_memo())
print("")
caretaker.undo()
print(notepad.get_memo())
print(caretaker.show_history())