概要
Prototype パターンは、GoF デザインパターンの一つで、生成に関するデザインパターンです。
オブジェクトの生成コストが高い場合や、同じ設定を持つオブジェクトを大量に作りたい場合に、 既存のインスタンスをテンプレートとして複製(Clone)することで効率的にオブジェクトを生成します。
ゲーム開発においては、同じ設定の敵キャラクターやアイテムを大量にスポーンする場面でよく活用されます。 毎回ゼロからオブジェクトを構築するより、プロトタイプをコピーするほうが処理コストを抑えられます。
構成
classDiagram
class IPrototype {
<< interface >>
+ Clone() IPrototype
}
class ConcretePrototype {
+ field1
+ field2
+ Clone() IPrototype
}
ConcretePrototype ..|> IPrototype : implements
Client ..> IPrototype : << use >>
| 要素 | 役割 |
|---|---|
| IPrototype | Clone() メソッドを定義するインターフェース |
| ConcretePrototype | 実際にクローン処理を実装するクラス |
| Client | プロトタイプを複製して使う利用者 |
実装例(C#)
クラス概要
早速実装例です。今回はC#でゲーム開発を行う場合を想定してみました。
利用ケースは以下のように、敵キャラクターのプロトタイプを複製してスポーンさせる機構です。
IEnemy:プロトタイプインターフェース(IPrototype)Slime・Dragon:複製可能な敵クラス(Concrete Prototype)- クライアント:プロトタイプを複製して敵をスポーン
ソースコード
1. プロトタイプインターフェース(IPrototype)
/// <summary>
/// 敵のプロトタイプインターフェース (IPrototype)
/// </summary>
public interface IEnemy
{
string Name { get; }
int Hp { get; }
int Attack { get; }
/// <summary>自分自身を複製して返す</summary>
IEnemy Clone();
void ShowInfo();
}2. 具象プロトタイプ(Concrete Prototype)
using System;
/// <summary>
/// スライム (Concrete Prototype)
/// </summary>
public class Slime : IEnemy
{
public string Name { get; private set; }
public int Hp { get; private set; }
public int Attack { get; private set; }
public Slime(string name, int hp, int attack)
{
Name = name;
Hp = hp;
Attack = attack;
}
/// <summary>MemberwiseClone で浅いコピーを返す</summary>
public IEnemy Clone() => (IEnemy)this.MemberwiseClone();
public void ShowInfo() =>
Console.WriteLine($"[{Name}] HP:{Hp} ATK:{Attack}");
}
/// <summary>
/// ドラゴン (Concrete Prototype)
/// </summary>
public class Dragon : IEnemy
{
public string Name { get; private set; }
public int Hp { get; private set; }
public int Attack { get; private set; }
public string Element { get; private set; }
public Dragon(string name, int hp, int attack, string element)
{
Name = name;
Hp = hp;
Attack = attack;
Element = element;
}
public IEnemy Clone() => (IEnemy)this.MemberwiseClone();
public void ShowInfo() =>
Console.WriteLine($"[{Name}({Element})] HP:{Hp} ATK:{Attack}");
}C# の MemberwiseClone() を使うとフィールドを浅いコピーで複製できます。
深いコピー(deepcopy: 参照型フィールドも含めて独立させる)が必要な場合は、コピーコンストラクタや手動コピーを実装します。
3. クライアントコード
class PrototypeSample
{
static void Main()
{
// プロトタイプとなるインスタンスを1つ作成
IEnemy slimeProto = new Slime("スライム", 30, 5);
IEnemy dragonProto = new Dragon("ドラゴン", 500, 80, "炎");
// プロトタイプを複製してスポーン
IEnemy slime1 = slimeProto.Clone();
IEnemy slime2 = slimeProto.Clone();
IEnemy boss = dragonProto.Clone();
slime1.ShowInfo(); // => [スライム] HP:30 ATK:5
slime2.ShowInfo(); // => [スライム] HP:30 ATK:5
boss.ShowInfo(); // => [ドラゴン(炎)] HP:500 ATK:80
// 複製元と複製先は別インスタンス
Console.WriteLine(ReferenceEquals(slimeProto, slime1)); // => False
}
}使いどころ
- 同じ設定を持つオブジェクトを大量に生成したいとき(敵の大量スポーン)
- オブジェクトの生成コストが高く、毎回ゼロから作るのが非効率なとき
- 生成するクラスに直接依存させたくないとき(インターフェース経由でClone)
長所・短所
✅ 長所
- 既存インスタンスを複製するため、初期化コストを削減できる
- 具体的なクラスに依存せずにオブジェクトを生成できる
- 複雑な初期化処理を持つオブジェクトを簡単に複製できる
⚠️ 短所
- 深いコピーが必要な場合、実装が複雑になる
- 循環参照を持つオブジェクトのクローンは特別な対応が必要
MemberwiseClone()の浅いコピーで十分かどうかを常に意識する必要がある
他GoFパターンとの比較・関係
Factory Method / Abstract Factory との違い
Factory Method や Abstract Factory は「クラスからオブジェクトを new して生成する」仕組みです。 Prototype は「既存のインスタンスをコピーして生成する」点が根本的に異なります。
生成元がクラスか、インスタンスかという違いです。
| パターン | 生成の起点 |
|---|---|
| Factory Method | クラス定義(new) |
| Abstract Factory | クラス定義(new)の組み合わせ |
| Prototype | 既存インスタンス(Clone) |
Builder との関係
Builder は「手順を踏んで段階的に組み立てる」パターンです。
Prototype は「完成済みのオブジェクトをコピーする」パターンです。
初期設定が複雑なオブジェクトを Builder で一度組み立て、それを Prototype で複製するという組み合わせもよく使われます。
Singleton との関係
Prototype で複製元となるプロトタイプオブジェクトを Singleton で管理するパターンも一般的です。 「どこからでも同一のプロトタイプにアクセスし、そこから複製する」という設計です。
まとめ
- Prototype パターンは、既存インスタンスを複製(Clone)して新しいオブジェクトを生成する
- C# では
MemberwiseClone()で浅いコピーを、参照型フィールドがある場合は深いコピーを実装する - ゲーム開発では敵キャラやアイテムの大量スポーンに有効
- Factory Method との違いは「クラスから new」か「インスタンスからコピー」かにある
- Builder で組み立てたオブジェクトを Prototype で複製するパターンもよく使われる

