概要
Prototype(プロトタイプ)パターンは、
インスタンスの生成をコンストラクタ(__init__
)によらず、既存オブジェクトを複製(clone)することで実現する設計パターンである。
同じ構造のオブジェクトを大量に生成したい場合や、初期化コストが高いオブジェクトの再利用などに有効。
複雑な構築ロジックをカプセル化し、コピーによる柔軟な生成制御が可能となる。
1. なぜPrototypeが必要か?
❌ 毎回コンストラクタで初期化すると、設定・構築処理が重複する
user = User("admin", permissions=["read", "write", "delete"])
→ 似たような構造のオブジェクトを都度構築するのは非効率
✅ ベースとなるオブジェクトを複製し、必要に応じて差分だけ上書き
admin = prototype.clone()
admin.name = "root"
→ 共通の構造をコピーして活用できるため、保守性と効率が高まる
2. 基本構造
✅ Prototypeインターフェース
import copy
class Prototype:
def clone(self):
return copy.deepcopy(self)
✅ 利用クラスの定義
class User(Prototype):
def __init__(self, name, permissions):
self.name = name
self.permissions = permissions
def show(self):
print(f"User: {self.name}, Permissions: {self.permissions}")
✅ 使用例
base_user = User("template", ["read", "write"])
admin_user = base_user.clone()
admin_user.name = "admin"
admin_user.permissions.append("delete")
guest_user = base_user.clone()
guest_user.name = "guest"
guest_user.permissions = ["read"]
base_user.show() # template, ["read", "write"]
admin_user.show() # admin, ["read", "write", "delete"]
guest_user.show() # guest, ["read"]
出力:
User: template, Permissions: ['read', 'write']
User: admin, Permissions: ['read', 'write', 'delete']
User: guest, Permissions: ['read']
3. Python的応用:copy.copy
vs copy.deepcopy
from copy import copy, deepcopy
a = [1, 2, [3, 4]]
shallow = copy(a)
deep = deepcopy(a)
a[2].append(5)
print(shallow) # [1, 2, [3, 4, 5]] ← 浅いコピーは内部リストを共有
print(deep) # [1, 2, [3, 4]] ← 深いコピーは独立している
→ 浅い vs 深い の違いは、Prototype設計において極めて重要
4. 実務ユースケース
✅ テンプレートオブジェクトからの生成
→ フォーム、ユーザー、設定など共通構造の複製
✅ 初期化コストの高いオブジェクトの再利用
→ DB接続、外部リソース、構文解析済み構造など
✅ テスト・モック用の状態複製
→ 状態を維持したまま環境をコピーしてシナリオ分岐
✅ ゲームにおけるエンティティ・アイテムの生成
→ 元データから個体差を持たせて生成
5. よくある誤用と対策
❌ clone() における浅いコピーが意図せず副作用を引き起こす
→ ✅ deepcopy()
をデフォルトとし、明示的な制御が必要なときのみ copy()
を使用
❌ 複製後に必須の初期化を忘れると、不完全なオブジェクトになる
→ ✅ clone後に initialize()
的なメソッドを呼び出すパターンを設計に含める
❌ データと振る舞いを分離しないまま複製して状態を混乱させる
→ ✅ 状態とロジックの分離(データクラス化・DI設計)を併用
結語
Prototypeパターンとは、“作るのではなく、写すことで構造を再利用する設計”である。
- コンストラクションの重さを回避し、共通構造の複製により生成の効率性を確保
- 状態のコピーを前提とするため、柔軟かつ迅速なインスタンス展開が可能
- Pythonでは
copy
モジュールによって、シンプルに強力なPrototype戦略を実現できる
Pythonicとは、“繰り返すより、写してから変えること”。
Prototypeパターンはその複製の知性を、設計の俊敏性として表現する技法である。