工厂方法模式

在Unity中使用C#实现工厂方法模式,结合游戏开发的典型场景(比如创建不同类型的游戏角色:战士、法师、弓箭手),能更贴合实际开发需求。以下是完整的可运行示例,包含核心角色定义、工厂实现和Unity场景调用逻辑。

一、核心思路(工厂方法模式)

角色 对应实现类 作用
产品接口/抽象类 ICharacter(接口) 定义所有游戏角色的通用行为(移动、攻击)
具体产品 Warrior/Mage/Archer 实现ICharacter,封装不同角色的具体行为
工厂抽象类/接口 CharacterFactory(抽象类) 定义创建角色的抽象方法CreateCharacter()
具体工厂 WarriorFactory/MageFactory/ArcherFactory 实现抽象工厂,负责创建对应具体角色,可附加Unity特有的初始化逻辑(如加载预制体)
客户端 GameManager(挂载到Unity物体) 调用具体工厂创建角色,无需直接new对象

二、完整代码实现

1. 产品接口:ICharacter(定义角色通用行为)

/// <summary>
/// 游戏角色接口(产品接口)
/// </summary>
public interface ICharacter
{
    // 角色名称
    string Name { get; }
    // 移动行为
    void Move();
    // 攻击行为
    void Attack();
}

2. 具体产品:不同角色实现(战士、法师、弓箭手)

/// <summary>
/// 战士(具体产品1)
/// </summary>
public class Warrior : ICharacter
{
    public string Name => "战士";

    public void Move()
    {
        Debug.Log($"{Name}:持盾冲锋!");
    }

    public void Attack()
    {
        Debug.Log($"{Name}:挥剑斩击,造成物理伤害!");
    }
}

/// <summary>
/// 法师(具体产品2)
/// </summary>
public class Mage : ICharacter
{
    public string Name => "法师";

    public void Move()
    {
        Debug.Log($"{Name}:闪现移动!");
    }

    public void Attack()
    {
        Debug.Log($"{Name}:释放火球术,造成魔法伤害!");
    }
}

/// <summary>
/// 弓箭手(具体产品3)
/// </summary>
public class Archer : ICharacter
{
    public string Name => "弓箭手";

    public void Move()
    {
        Debug.Log($"{Name}:翻滚走位!");
    }

    public void Attack()
    {
        Debug.Log($"{Name}:射出穿云箭,造成远程伤害!");
    }
}

3. 工厂抽象类:CharacterFactory(定义创建角色的抽象方法)

/// <summary>
/// 角色工厂抽象类(工厂接口)
/// </summary>
public abstract class CharacterFactory
{
    /// <summary>
    /// 创建角色的抽象方法(工厂方法)
    /// </summary>
    /// <returns>具体角色实例</returns>
    public abstract ICharacter CreateCharacter();

    // 可选:添加Unity特有的通用逻辑(比如加载角色预制体、初始化位置)
    protected void InitCharacterGameObject(string characterName)
    {
        Debug.Log($"[{characterName}] 预制体加载完成,初始化位置为(0,0,0)");
        // 实际项目中可在这里加载Resources中的预制体、设置父物体等
        // GameObject prefab = Resources.Load<GameObject>($"Prefabs/{characterName}");
        // GameObject characterObj = Object.Instantiate(prefab, Vector3.zero, Quaternion.identity);
    }
}

4. 具体工厂:对应角色的工厂实现

/// <summary>
/// 战士工厂(具体工厂1)
/// </summary>
public class WarriorFactory : CharacterFactory
{
    public override ICharacter CreateCharacter()
    {
        // 调用通用初始化逻辑(Unity预制体、位置等)
        InitCharacterGameObject("Warrior");
        // 创建并返回战士实例
        return new Warrior();
    }
}

/// <summary>
/// 法师工厂(具体工厂2)
/// </summary>
public class MageFactory : CharacterFactory
{
    public override ICharacter CreateCharacter()
    {
        InitCharacterGameObject("Mage");
        return new Mage();
    }
}

/// <summary>
/// 弓箭手工厂(具体工厂3)
/// </summary>
public class ArcherFactory : CharacterFactory
{
    public override ICharacter CreateCharacter()
    {
        InitCharacterGameObject("Archer");
        return new Archer();
    }
}

5. 客户端调用:GameManager(挂载到Unity物体运行)

using UnityEngine;

/// <summary>
/// 游戏管理器(客户端):调用工厂创建角色
/// </summary>
public class GameManager : MonoBehaviour
{
    private void Start()
    {
        // 1. 创建战士(通过战士工厂)
        CharacterFactory warriorFactory = new WarriorFactory();
        ICharacter warrior = warriorFactory.CreateCharacter();
        warrior.Move();
        warrior.Attack();

        Debug.Log("————————分割线————————");

        // 2. 创建法师(通过法师工厂)
        CharacterFactory mageFactory = new MageFactory();
        ICharacter mage = mageFactory.CreateCharacter();
        mage.Move();
        mage.Attack();

        Debug.Log("————————分割线————————");

        // 3. 创建弓箭手(通过弓箭手工厂)
        CharacterFactory archerFactory = new ArcherFactory();
        ICharacter archer = archerFactory.CreateCharacter();
        archer.Move();
        archer.Attack();
    }
}

三、Unity中运行效果

  1. GameManager脚本挂载到Unity场景中的任意空物体(比如MainCamera);
  2. 运行场景,控制台输出如下:
[Warrior] 预制体加载完成,初始化位置为(0,0,0)
战士:持盾冲锋!
战士:挥剑斩击,造成物理伤害!
————————分割线————————
[Mage] 预制体加载完成,初始化位置为(0,0,0)
法师:闪现移动!
法师:释放火球术,造成魔法伤害!
————————分割线————————
[Archer] 预制体加载完成,初始化位置为(0,0,0)
弓箭手:翻滚走位!
弓箭手:射出穿云箭,造成远程伤害!

四、Unity开发中的扩展技巧

  1. 结合预制体加载
    实际项目中,可在具体工厂的CreateCharacter方法中加载角色预制体,示例:

    public override ICharacter CreateCharacter()
    {
        // 加载预制体
        GameObject magePrefab = Resources.Load<GameObject>("Prefabs/Mage");
        GameObject mageObj = Instantiate(magePrefab, Vector3.zero, Quaternion.identity);
        // 给预制体挂载角色逻辑组件
        Mage mage = mageObj.AddComponent<Mage>();
        InitCharacterGameObject("Mage");
        return mage;
    }
    

    注意:需将Mage/Warrior等类改为继承MonoBehaviour,适配Unity组件化开发。

  2. 工厂池化优化
    若角色频繁创建/销毁,可在工厂中集成对象池(Object Pool),复用已有角色实例,减少GC:

    public class WarriorFactory : CharacterFactory
    {
        private ObjectPool<Warrior> _warriorPool;
    
        public WarriorFactory()
        {
            // 初始化对象池
            _warriorPool = new ObjectPool<Warrior>(
                createFunc: () => new Warrior(),
                actionOnGet: (w) => Debug.Log($"复用{w.Name}实例"),
                actionOnRelease: (w) => Debug.Log($"回收{w.Name}实例")
            );
        }
    
        public override ICharacter CreateCharacter()
        {
            return _warriorPool.Get();
        }
    
        // 回收角色到池
        public void ReleaseWarrior(Warrior warrior)
        {
            _warriorPool.Release(warrior);
        }
    }
    
  3. 动态切换工厂
    可通过配置表、UI按钮事件动态选择工厂,比如点击“创建法师”按钮时实例化MageFactory

    public void OnCreateMageButtonClick()
    {
        CharacterFactory factory = new MageFactory();
        ICharacter mage = factory.CreateCharacter();
        mage.Attack();
    }
    

五、工厂方法模式的优势(Unity场景)

  1. 解耦:客户端(GameManager)无需知道角色的具体创建逻辑,只需调用工厂方法;
  2. 易扩展:新增角色(比如“刺客”)时,只需新增Assassin(具体产品)和AssassinFactory(具体工厂),无需修改原有代码,符合“开闭原则”;
  3. 统一管理:角色的初始化(预制体加载、位置设置、组件挂载)都集中在工厂中,便于维护。