Unityで学ぶファクトリーパターンとファクトリーメソッドパターン チュートリアル

~ 武器生成例を通して学ぶ ~

このチュートリアルでは、Unity環境でファクトリーパターン(特にファクトリーメソッドパターン)を利用して、武器(剣や弓)を生成する方法を解説します。デザインパターンの基本概念を学びながら、実際に動作するサンプルコードを通して実装方法を理解できる内容となっています。


1. はじめに

ファクトリーパターンとは

ファクトリーパターンは、オブジェクトの生成処理をクライアントコードから分離し、柔軟かつ拡張性のある設計を実現するためのパターンです。これにより、生成するオブジェクトの種類が増えてもクライアント側の変更を最小限に抑えることができます。

ファクトリーメソッドパターンとは

ファクトリーメソッドパターンは、ファクトリーパターンの一種であり、抽象クラスやインターフェースに定義されたファクトリーメソッドを、サブクラス(派生クラス)がオーバーライドして具体的なオブジェクトを生成します。この手法を用いることで、生成ロジックの変更をサブクラス(派生クラス)でカプセル化でき、拡張性が向上します。


2. チュートリアルの内容

このチュートリアルでは、以下のステップでサンプルコードを作成します。

  1. 武器のインターフェース IWeapon を作成し、基本的な攻撃機能を定義
  2. 具体的な武器クラス SwordBow を作成し、各々の攻撃方法を実装
  3. 抽象クラス WeaponCreator を作成し、ファクトリーメソッド CreateWeapon を定義
  4. 具体的なクリエータークラス SwordCreatorBowCreator を作成し、各武器の生成を実装(ここで各具体クラスはサブクラス(派生クラス)となります)
  5. MonoBehaviour クラス WeaponFactoryTest を作成し、シーン起動時に各武器を生成して攻撃を実行

3. Unity用サンプルコード

以下のコードをUnityプロジェクト内に作成してください。
この例では、各クラスを1つのスクリプトにまとめても構いませんし、ファイルを分割して管理してもかまいません。

using UnityEngine;

// 1. 武器(Weapon)のインターフェース
public interface IWeapon
{
    void Attack();
}

// 2. 具体的な武器:剣
public class Sword : IWeapon
{
    public void Attack()
    {
        Debug.Log("剣による攻撃!");
    }
}

// 3. 具体的な武器:弓
public class Bow : IWeapon
{
    public void Attack()
    {
        Debug.Log("弓による攻撃!");
    }
}

// 4. クリエーター(WeaponCreator)抽象クラス
public abstract class WeaponCreator
{
    // ファクトリーメソッド:サブクラス(派生クラス)で具体的な武器生成を実装
    public abstract IWeapon CreateWeapon();

    // 共通処理:生成した武器で攻撃を実行
    public void AttackWithWeapon()
    {
        IWeapon weapon = CreateWeapon();
        weapon.Attack();
    }
}

// 5. 具体的なクリエーター:SwordCreator(剣を生成)
public class SwordCreator : WeaponCreator
{
    public override IWeapon CreateWeapon()
    {
        return new Sword();
    }
}

// 6. 具体的なクリエーター:BowCreator(弓を生成)
public class BowCreator : WeaponCreator
{
    public override IWeapon CreateWeapon()
    {
        return new Bow();
    }
}

// 7. テスト用 MonoBehaviour クラス
public class WeaponFactoryTest : MonoBehaviour
{
    // Start メソッドで生成した武器による攻撃を実行
    private void Start()
    {
        // 剣を生成して攻撃
        WeaponCreator swordCreator = new SwordCreator();
        swordCreator.AttackWithWeapon();

        // 弓を生成して攻撃
        WeaponCreator bowCreator = new BowCreator();
        bowCreator.AttackWithWeapon();
    }
}

4. セットアップ手順

  1. Unityプロジェクトの作成
    Unity Hubから新規プロジェクトを作成し、適切なテンプレート(例:3D)を選択してください。
  2. スクリプトの作成
    上記のコードをコピーし、WeaponFactoryTest.cs という名前で Assets フォルダ内に作成します。
    ※ ファイルを分割する場合は、各クラスごとにスクリプトを作成してください。
  3. GameObjectへのアタッチ
    シーン内に空のGameObjectを作成し、先ほど作成した WeaponFactoryTest スクリプトをアタッチします。
  4. シーンの再生
    シーンを再生すると、Unityのコンソールに「剣による攻撃!」と「弓による攻撃!」のメッセージが表示され、ファクトリーメソッドパターンによるオブジェクト生成と処理実行を確認できます。

5. まとめ

  • ファクトリーパターンは、オブジェクト生成の責任を分離し、クライアントコードの保守性を向上させます。
  • ファクトリーメソッドパターンは、抽象クラスまたはインターフェースに定義されたメソッドを、サブクラス(派生クラス)が実装することで、具体的な生成処理を隠蔽します。
  • 本チュートリアルでは、武器(剣・弓)の例を通じて、Unity環境での実装方法とその効果を学びました。

このチュートリアルを通じて、Unityにおけるデザインパターンの実践方法や、柔軟なオブジェクト生成の実装について理解を深めてください。

ファクトリーメソッドパターンは、特に以下の場合に非常に有用です。

  • 拡張性の向上: 新たな武器(あるいはオブジェクト)が増える可能性がある場合、生成ロジックをサブクラス(派生クラス)に委譲することで、既存のコードに影響を与えずに新たな機能を追加できます。
  • クライアントコードの単純化: クライアントは具体的な実装クラスを意識せずにインターフェースを使えるため、コードの保守性が向上します。
  • 依存性の低減: 直接newキーワードでインスタンス生成を行わないため、クラス間の依存関係が緩やかになり、テストや変更が容易になります。

ただし、プロジェクトが小規模で生成するオブジェクトの種類が固定されている場合、あえてこのパターンを使うと過剰設計になってしまう可能性もあります。

結論としては、プロジェクトの規模や将来的な拡張性、保守性の観点から判断する必要があります。設計が複雑になったり、拡張の余地がある場合には積極的に利用すべきですが、シンプルなケースではシンプルな実装で十分なこともあります。