Python基礎 オブジェクト指向7(Prototype) 生成に関するデザインパターン
| 登録日 | :2025/09/27 21:13 |
|---|---|
| カテゴリ | :Python基礎 |
Prototypeとは
原型となるインスタンスをコピーして新しいインスタンスを生成するパターン
親クラスでインスタンスをコピーするためのメソッドを定義し、子クラスで自分自身のコピーを返すように実装する
生成に関するデザインパターン
浅いコピー・深いコピー
浅いコピー
- 変数に格納された値がそのままコピーされる
- オブジェクトの参照を格納した変数では、参照がコピーされる
=>どちらかのオブジェクトを変更すると、もう片方も変更される
深いコピー
- オブジェクトの参照を格納した変数では、実体がコピーされる
=>どちらかのオブジェクトを変更しても、もう片方に影響を与えない
ただし、デメリットとしてコピーするときにメモリやCPUなどの負荷がかかることに注意
構成要素
Manager
- コピーするオブジェクトを管理しつつ、インスタンスを要求された際にコピーを返す
Prototype
- インターフェースもしくは抽象クラス
- インスタンスをコピーして新しいインスタンスを作るためのメソッドを定める
ConcretePrototype
- Prototypeを実装(継承)する子クラス
- Prototypeで定義されたコピー用のメソッドを実装する
オブジェクト指向的要素
「継承」と「ポリモーフィズム」を利用したパターン
- PrototypekeyとConcretePrototypeクラスの間に継承(実装)関係
- Managerは親クラスであるPrototypeクラスで提供されているAPIのみを使ってプログラミングを行う
- ManagerとConcretePrototypeに依存関係がないので、ConcretePrototypeの差し替えや追加。修正が可能
メリット・デメリット
メリット
- オブジェクトの生成処理を隠蔽できる
- 構築済みのプロトタイプのクローンの作成を使うことにより、初期化コードの重複を削減
- 利用者と具体的なクラスの結合度を弱められる
デメリット
- 浅いコピー(sharrow copy)と深いコピー(deep copy)を意識していないと、想定外のバグを生む可能性がある。
使い所
-
クラスからのインスタンス生成が難しい場合
ユーザー操作によって生成されたグラフィックオブジェクトなど
例)パワーポイントの図形のコピー -
インスタンス化のコストがコピーよりも高い場合
サンプルコード
from __future__ import annotations
import copy
from abc import ABCMeta, abstractmethod
from typing import List, Union
class ItemPrototype(metaclass=ABCMeta):
def __init__(self, _name: str):
self.__name = _name
self.__review: List[str] = []
def __str__(self):
return f"{self.__name}: {self.__review}"
def set_review(self, _review: str):
self.__review.append(_review)
@abstractmethod
def create_copy(self) -> ItemPrototype:
pass
class DeepCopyItem(ItemPrototype):
def create_copy(self) -> ItemPrototype:
return copy.deepcopy(self)
class ShallowCopyItem(ItemPrototype):
def create_copy(self) -> ItemPrototype:
return copy.copy(self)
class ItemManager(object):
def __init__(self):
self.items = {}
def register_item(self, _key: str, _item: ItemPrototype):
self.items[_key] = _item
def create(self, _key: str) -> Union[ItemPrototype, None]:
if _key in self.items:
item = self.items[_key]
return item.create_copy()
raise Exception("指定されたKeyが存在しません")
if __name__ == '__main__':
mouse = DeepCopyItem('Mouse')
Keyboard = ShallowCopyItem('Keyboard')
manager = ItemManager()
manager.register_item("mouse", mouse)
manager.register_item("keyboard", Keyboard)
cloned_mouse = manager.create("mouse")
cloned_keyboard = manager.create("keyboard")
cloned_mouse.set_review("Good!")
cloned_keyboard.set_review("SoSo!")
print("")
print("mouse(original):", mouse)
print("mouse(copy):", cloned_mouse)
print("")
print("keyboard(original)", Keyboard)
print("keyboard(copy)", cloned_keyboard)