抽象工厂模式

在Unity中使用C#实现抽象工厂模式,核心是解决「创建一组相关/依赖的产品族」问题(而非单一产品)。结合游戏开发典型场景——不同阵营(人类/兽人)的配套角色+武器(人类战士+剑、兽人战士+战斧;人类法师+法杖、兽人法师+狼牙棒),能直观体现抽象工厂“生产产品族”的核心特性。

一、核心思路(抽象工厂模式)

角色 对应实现类 作用
抽象产品A ICharacter(角色接口) 定义所有角色的通用行为(移动、攻击)
抽象产品B IWeapon(武器接口) 定义所有武器的通用行为(攻击、展示)
具体产品A1/A2 HumanWarrior/OrcWarrior 人类/兽人战士(实现ICharacter
具体产品B1/B2 Sword/BattleAxe 剑/战斧(实现IWeapon
抽象工厂 ICampFactory(阵营工厂接口) 定义创建“角色+武器”产品族的抽象方法(CreateCharacter()+CreateWeapon()
具体工厂 HumanCampFactory/OrcCampFactory 人类/兽人阵营工厂,实现抽象工厂,创建对应阵营的角色+武器
客户端 GameManager(挂载到Unity物体) 调用具体工厂,一次性创建配套的角色+武器,无需关注具体产品实现

二、完整代码实现

1. 抽象产品定义(角色+武器)

1.1 角色抽象产品:ICharacter
using UnityEngine;

/// <summary>
/// 角色抽象产品:定义所有角色的通用行为
/// </summary>
public interface ICharacter
{
    string Camp { get; } // 阵营(人类/兽人)
    string Name { get; } // 角色名称
    void Move();         // 移动行为
    void Attack(IWeapon weapon); // 攻击(依赖武器)
}
1.2 武器抽象产品:IWeapon
/// <summary>
/// 武器抽象产品:定义所有武器的通用行为
/// </summary>
public interface IWeapon
{
    string Name { get; } // 武器名称
    int AttackPower { get; } // 攻击力
    void ShowWeapon(); // 展示武器
}

2. 具体产品实现(人类/兽人配套角色+武器)

2.1 人类阵营具体产品
/// <summary>
/// 人类战士(具体产品A1)
/// </summary>
public class HumanWarrior : ICharacter
{
    public string Camp => "人类阵营";
    public string Name => "人类战士";

    public void Move()
    {
        Debug.Log($"{Camp}-{Name}:持盾稳步推进!");
    }

    public void Attack(IWeapon weapon)
    {
        Debug.Log($"{Camp}-{Name} 使用 {weapon.Name} 攻击,造成 {weapon.AttackPower} 点物理伤害!");
    }
}

/// <summary>
/// 剑(人类配套武器,具体产品B1)
/// </summary>
public class Sword : IWeapon
{
    public string Name => "圣光之剑";
    public int AttackPower => 80;

    public void ShowWeapon()
    {
        Debug.Log($"装备 {Name}:剑身散发圣光,攻击力+{AttackPower}");
    }
}
2.2 兽人阵营具体产品
/// <summary>
/// 兽人战士(具体产品A2)
/// </summary>
public class OrcWarrior : ICharacter
{
    public string Camp => "兽人阵营";
    public string Name => "兽人狂战士";

    public void Move()
    {
        Debug.Log($"{Camp}-{Name}:狂怒冲锋,势不可挡!");
    }

    public void Attack(IWeapon weapon)
    {
        Debug.Log($"{Camp}-{Name} 使用 {weapon.Name} 攻击,造成 {weapon.AttackPower} 点物理伤害!");
    }
}

/// <summary>
/// 战斧(兽人配套武器,具体产品B2)
/// </summary>
public class BattleAxe : IWeapon
{
    public string Name => "嗜血战斧";
    public int AttackPower => 100;

    public void ShowWeapon()
    {
        Debug.Log($"装备 {Name}:斧刃沾满鲜血,攻击力+{AttackPower}");
    }
}

3. 抽象工厂与具体工厂(生产产品族)

3.1 抽象工厂:ICampFactory(定义产品族创建接口)
/// <summary>
/// 阵营工厂抽象类(抽象工厂):定义创建“角色+武器”产品族的方法
/// </summary>
public interface ICampFactory
{
    // 创建阵营角色
    ICharacter CreateCharacter();
    // 创建配套武器
    IWeapon CreateWeapon();
}
3.2 具体工厂:人类/兽人阵营工厂
/// <summary>
/// 人类阵营工厂(具体工厂1):生产人类角色+配套武器
/// </summary>
public class HumanCampFactory : ICampFactory
{
    public ICharacter CreateCharacter()
    {
        // Unity特有逻辑:可在此加载人类战士预制体、初始化位置等
        Debug.Log("[人类阵营工厂] 加载人类战士预制体完成!");
        return new HumanWarrior();
    }

    public IWeapon CreateWeapon()
    {
        Debug.Log("[人类阵营工厂] 加载圣光之剑预制体完成!");
        return new Sword();
    }
}

/// <summary>
/// 兽人阵营工厂(具体工厂2):生产兽人角色+配套武器
/// </summary>
public class OrcCampFactory : ICampFactory
{
    public ICharacter CreateCharacter()
    {
        Debug.Log("[兽人阵营工厂] 加载兽人狂战士预制体完成!");
        return new OrcWarrior();
    }

    public IWeapon CreateWeapon()
    {
        Debug.Log("[兽人阵营工厂] 加载嗜血战斧预制体完成!");
        return new BattleAxe();
    }
}

4. 客户端调用:GameManager(Unity场景挂载)

using UnityEngine;

/// <summary>
/// 游戏管理器(客户端):调用抽象工厂创建完整产品族
/// </summary>
public class GameManager : MonoBehaviour
{
    private void Start()
    {
        // ========== 1. 创建人类阵营产品族(战士+剑) ==========
        Debug.Log("—————— 初始化人类阵营部队 ——————");
        ICampFactory humanFactory = new HumanCampFactory();
        ICharacter humanWarrior = humanFactory.CreateCharacter();
        IWeapon humanSword = humanFactory.CreateWeapon();
        
        humanWarrior.Move();
        humanSword.ShowWeapon();
        humanWarrior.Attack(humanSword);

        // ========== 2. 创建兽人阵营产品族(狂战士+战斧) ==========
        Debug.Log("\n—————— 初始化兽人阵营部队 ——————");
        ICampFactory orcFactory = new OrcCampFactory();
        ICharacter orcWarrior = orcFactory.CreateCharacter();
        IWeapon orcAxe = orcFactory.CreateWeapon();
        
        orcWarrior.Move();
        orcAxe.ShowWeapon();
        orcWarrior.Attack(orcAxe);
    }
}

三、Unity运行效果

GameManager挂载到场景任意物体(如MainCamera),运行后控制台输出:

—————— 初始化人类阵营部队 ——————
[人类阵营工厂] 加载人类战士预制体完成!
[人类阵营工厂] 加载圣光之剑预制体完成!
人类阵营-人类战士:持盾稳步推进!
装备 圣光之剑:剑身散发圣光,攻击力+80
人类阵营-人类战士 使用 圣光之剑 攻击,造成 80 点物理伤害!

—————— 初始化兽人阵营部队 ——————
[兽人阵营工厂] 加载兽人狂战士预制体完成!
[兽人阵营工厂] 加载嗜血战斧预制体完成!
兽人阵营-兽人狂战士:狂怒冲锋,势不可挡!
装备 嗜血战斧:斧刃沾满鲜血,攻击力+100
兽人阵营-兽人狂战士 使用 嗜血战斧 攻击,造成 100 点物理伤害!

四、Unity场景扩展(贴合实际开发)

1. 新增产品族(法师+法杖/狼牙棒)

抽象工厂模式的核心优势是扩展产品族便捷,新增“法师+专属武器”产品族时,仅需:

1.1 新增具体产品(法师+法杖/狼牙棒)
// 人类法师(新增具体产品A1-2)
public class HumanMage : ICharacter
{
    public string Camp => "人类阵营";
    public string Name => "人类法师";

    public void Move() => Debug.Log($"{Camp}-{Name}:闪现移动!");
    public void Attack(IWeapon weapon) => Debug.Log($"{Camp}-{Name} 使用 {weapon.Name} 释放法术,造成 {weapon.AttackPower} 点魔法伤害!");
}

// 法杖(人类法师配套武器,新增具体产品B1-2)
public class Staff : IWeapon
{
    public string Name => "元素法杖";
    public int AttackPower => 120;
    public void ShowWeapon() => Debug.Log($"装备 {Name}:法杖汇聚元素之力,攻击力+{AttackPower}");
}

// 兽人法师+狼牙棒(同理,略)
1.2 扩展抽象工厂(新增创建法师的方法)
public interface ICampFactory
{
    ICharacter CreateCharacter(); // 战士
    ICharacter CreateMage();      // 新增:法师
    IWeapon CreateWeapon();       // 战士武器
    IWeapon CreateMageWeapon();   // 新增:法师武器
}

// 人类工厂实现新增方法
public class HumanCampFactory : ICampFactory
{
    // 原有方法...
    public ICharacter CreateMage() => new HumanMage();
    public IWeapon CreateMageWeapon() => new Staff();
}

2. 结合Unity预制体与组件化

实际项目中,可将产品类改为MonoBehaviour,在工厂中加载预制体并挂载组件:

public class HumanWarrior : MonoBehaviour, ICharacter
{
    public string Camp => "人类阵营";
    public string Name => "人类战士";

    public void Move() => Debug.Log($"{Camp}-{Name} 移动!");
    public void Attack(IWeapon weapon) => Debug.Log($"{Camp}-{Name} 用 {weapon.Name} 攻击!");
}

// 人类工厂中加载预制体
public class HumanCampFactory : ICampFactory
{
    public ICharacter CreateCharacter()
    {
        // 加载Resources下的人类战士预制体
        GameObject prefab = Resources.Load<GameObject>("Prefabs/HumanWarrior");
        GameObject warriorObj = Instantiate(prefab, Vector3.zero, Quaternion.identity);
        // 获取/添加角色组件
        HumanWarrior warrior = warriorObj.GetComponent<HumanWarrior>() ?? warriorObj.AddComponent<HumanWarrior>();
        return warrior;
    }

    // 武器同理...
}

3. 配置化切换工厂(避免硬编码)

通过ScriptableObject配置表管理工厂类型,动态切换阵营:

// 阵营配置表
[CreateAssetMenu(fileName = "CampConfig", menuName = "Game/CampConfig")]
public class CampConfig : ScriptableObject
{
    public enum CampType { Human, Orc }
    public CampType currentCamp;

    // 根据配置获取工厂
    public ICampFactory GetCampFactory()
    {
        return currentCamp switch
        {
            CampType.Human => new HumanCampFactory(),
            CampType.Orc => new OrcCampFactory(),
            _ => throw new System.ArgumentOutOfRangeException()
        };
    }
}

// 客户端调用
public class GameManager : MonoBehaviour
{
    public CampConfig campConfig; // 拖入配置文件

    private void Start()
    {
        ICampFactory factory = campConfig.GetCampFactory();
        ICharacter character = factory.CreateCharacter();
        // ...
    }
}

五、抽象工厂模式核心优势(Unity场景)

  1. 产品族一致性:确保同一阵营的角色和武器必然匹配(人类战士不会拿到兽人战斧),避免“产品不兼容”问题;
  2. 开闭原则:新增阵营(如精灵阵营)时,仅需新增ElfCampFactory+精灵角色+精灵武器,无需修改原有代码;
  3. 解耦高层模块:客户端(GameManager)仅依赖抽象工厂/产品接口,不关心具体实现,符合“依赖倒置原则”;
  4. 统一管理创建逻辑:所有阵营的预制体加载、初始化、组件挂载都集中在工厂中,便于维护。

六、抽象工厂 vs 工厂方法(Unity场景对比)

模式 核心差异 Unity适用场景
工厂方法 生产单一产品 创建单个角色/单个武器、简单道具生成
抽象工厂 生产一组配套产品族 阵营部队创建(角色+武器+坐骑)、UI皮肤套装(按钮+背景+字体)

抽象工厂是工厂方法的“升级版”,适合需要批量创建关联产品的场景,也是Unity中开发“套装化、阵营化”功能的首选模式。