0x03. 工厂方法模式
工厂方法模式
在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中运行效果
- 将
GameManager脚本挂载到Unity场景中的任意空物体(比如MainCamera); - 运行场景,控制台输出如下:
[Warrior] 预制体加载完成,初始化位置为(0,0,0)
战士:持盾冲锋!
战士:挥剑斩击,造成物理伤害!
————————分割线————————
[Mage] 预制体加载完成,初始化位置为(0,0,0)
法师:闪现移动!
法师:释放火球术,造成魔法伤害!
————————分割线————————
[Archer] 预制体加载完成,初始化位置为(0,0,0)
弓箭手:翻滚走位!
弓箭手:射出穿云箭,造成远程伤害!
四、Unity开发中的扩展技巧
-
结合预制体加载:
实际项目中,可在具体工厂的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组件化开发。 -
工厂池化优化:
若角色频繁创建/销毁,可在工厂中集成对象池(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); } } -
动态切换工厂:
可通过配置表、UI按钮事件动态选择工厂,比如点击“创建法师”按钮时实例化MageFactory:public void OnCreateMageButtonClick() { CharacterFactory factory = new MageFactory(); ICharacter mage = factory.CreateCharacter(); mage.Attack(); }
五、工厂方法模式的优势(Unity场景)
- 解耦:客户端(
GameManager)无需知道角色的具体创建逻辑,只需调用工厂方法; - 易扩展:新增角色(比如“刺客”)时,只需新增
Assassin(具体产品)和AssassinFactory(具体工厂),无需修改原有代码,符合“开闭原则”; - 统一管理:角色的初始化(预制体加载、位置设置、组件挂载)都集中在工厂中,便于维护。