概要
Prototype(プロトタイプ)パターンは、
既存のインスタンスをテンプレートとして、同じ構造のオブジェクトをコピーして生成する手法である。
インスタンス生成のコストが高い場合や、初期化の柔軟性が求められる場面で有効。
ファクトリパターンに似つつ、"コピーして生成"という思想に基づくのが特徴。
1. なぜPrototypeが必要か?
❌ 毎回 new や init で重い初期化を走らせる
user1 = User(name="admin", role="root", settings=heavy_config)
user2 = User(name="admin", role="root", settings=heavy_config)
→ 同じ構成を複数用意するたびに非効率
✅ 一度作成したプロトタイプをコピーして再利用
template = User(...)
clone = template.clone()
→ 軽量な複製でインスタンス生成を効率化
2. 基本構造
✅ Prototypeインターフェース
import copy
class Prototype:
def clone(self):
return copy.deepcopy(self)
✅ 対象クラスの実装
class User(Prototype):
def __init__(self, name, role, settings):
self.name = name
self.role = role
self.settings = settings
def __str__(self):
return f"User({self.name}, {self.role}, {self.settings})"
✅ 使用例
default_settings = {"theme": "dark", "language": "jp"}
admin = User("admin", "root", default_settings)
admin_clone = admin.clone()
admin_clone.name = "clone_admin"
print(admin) # User(admin, root, {'theme': 'dark', 'language': 'jp'})
print(admin_clone) # User(clone_admin, root, {'theme': 'dark', 'language': 'jp'})
→ 構造も含めて完全に複製できる
3. Python的応用:プロトタイプレジストリで汎用管理
class PrototypeRegistry:
def __init__(self):
self._prototypes = {}
def register(self, name, prototype):
self._prototypes[name] = prototype
def clone(self, name):
return self._prototypes[name].clone()
registry = PrototypeRegistry()
registry.register("admin", admin)
copy1 = registry.clone("admin")
copy2 = registry.clone("admin")
→ プロトタイプを名前付きで登録・複製できる柔軟な設計
4. 実務ユースケース
✅ テンプレートベースのフォーム・オブジェクト生成
→ 一度設定した構成を複製して使いまわす
✅ 大量オブジェクトの初期状態量産(ゲーム・UI)
→ 敵キャラやボタンなど同じ構造のインスタンスを高速に複製
✅ 設定済みのインスタンスをベースに派生インスタンス作成
→ 初期値の違いをわずかに与えたクローンを量産可能
✅ ファイル/DBから読み込んだ設定のクローンを使う
→ 一度読み込んだオブジェクトを動的にコピーして扱う
5. よくある誤用と対策
❌ clone が浅いコピー(shallow copy)で不整合発生
→ ✅ 必ず deepcopy を使用し、参照共有を避ける
❌ 複製後の属性変更がオリジナルに影響してしまう
→ ✅ ミューテーションを伴うフィールドは必ず検証
❌ clone ロジックがクラスごとにバラバラ
→ ✅ 共通の Prototype ベースクラスを導入して一貫性を保つ
結語
Prototypeパターンとは、“原型を鋳型として複製し、新たなオブジェクトを柔らかく生み出す設計”である。
- 初期化コストの高いインスタンスを効率よく再生成できる柔軟なアプローチ
- ファクトリでは表現しにくい“状態を含んだ生成”において強力なパターン
- Pythonでは
deepcopy()
と柔軟なクラス定義により、シンプルかつ効果的な実装が可能
Pythonicとは、“再利用と変化のバランスを、簡潔に保つこと”。
Prototypeパターンはその柔軟性と効率を、複製という技法に込めている。