0x04. 抽象工厂模式
抽象工厂模式
在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场景)
- 产品族一致性:确保同一阵营的角色和武器必然匹配(人类战士不会拿到兽人战斧),避免“产品不兼容”问题;
- 开闭原则:新增阵营(如精灵阵营)时,仅需新增
ElfCampFactory+精灵角色+精灵武器,无需修改原有代码; - 解耦高层模块:客户端(
GameManager)仅依赖抽象工厂/产品接口,不关心具体实现,符合“依赖倒置原则”; - 统一管理创建逻辑:所有阵营的预制体加载、初始化、组件挂载都集中在工厂中,便于维护。
六、抽象工厂 vs 工厂方法(Unity场景对比)
| 模式 | 核心差异 | Unity适用场景 |
|---|---|---|
| 工厂方法 | 生产单一产品 | 创建单个角色/单个武器、简单道具生成 |
| 抽象工厂 | 生产一组配套产品族 | 阵营部队创建(角色+武器+坐骑)、UI皮肤套装(按钮+背景+字体) |
抽象工厂是工厂方法的“升级版”,适合需要批量创建关联产品的场景,也是Unity中开发“套装化、阵营化”功能的首选模式。