抽象工厂模式(Abstract Factory Pattern). 它是一种创建型设计模式, 核心思想是: 提供一个接口, 用于创建一组相关或相互依赖的”产品家族”, 儿不许指定它们的具体类.
简单说: 抽象工厂就像”专属生产线” ——— 比如游戏里的 “人类阵营生产线” 能生产人力的武器\防具\坐骑; “精灵阵营生产线”能生产精灵的武器\防具\坐骑. 客户端只需要选择对应的”生产线”, 就能一键获取整套配套产品, 不用关心产品具体是怎么造的.
生活中的例子: 电子产品套装
不同品牌的“电子产品套装”就是产品家族:
- 苹果工厂: 生产 iPhone(手机) + Mac(电脑) + AirPods(耳机) (一套苹果生态产品)
- 华为工厂: 生产 Mate 手机 + MateBook 电脑 + FreeBuds 耳机(一套华为生态产品)
你(客户端)只需要选择”苹果工厂”或”华为工厂”, 就能得到一整套兼容的产品, 不用分别区买手机\电脑\耳机, 也不用关心它们的生产细节.
Unity中的核心场景: 阵营装备系统
假设我们开发一款 RPG 游戏, 有3个阵营(人类\精灵\兽人), 每个阵营都有专属的装备家族(武器 + 防具 + 坐骑), 且同一阵营的装备风格\属性相互匹配:
阵营 | 武器(产品1) | 防具(产品2) | 坐骑(产品3) |
人类 | 铁剑(近战) | 铁甲(高防御) | 战马(高速) |
精灵 | 长弓(远程) | 皮甲(高敏捷) | 巨鹿(隐身) |
兽人 | 巨斧(蛮力) | 石甲(高血量) | 野猪(冲撞) |
不用抽象工厂模式的问题:
如果直接在客户端代码里创建装备, 会出现大量
if-else , 且产品创建与使用强耦合:- 耦合度极高: 客户端要知道每个阵营的所有装备细节;
- 扩展困难: 新增阵营 / 装备, 需修改客户端的
if-else;
- 维护复杂: 装备创建逻辑分散, 无法统一管理.
用抽象工厂模式重构: 核心角色
抽象工厂模式有5个核心角色, 对应Unity场景如下:
模式角色 | Unity 场景映射 | 作用 |
抽象产品(Abstract Product) | IWeapon\IArmor\IMount | 定义同一类型产品的接口(如武器的攻击方法) |
具体产品(Concrete Product) | Sword\Bow\IronArmor等 | 每个阵营的具体装备, 实现抽象产品接口 |
抽象工厂(Abstract Factory) | ICampFactory | 定义创建”产品家族”的方法(创建武器\防具\坐骑) |
具体工厂(Concrete Factory) | HumanCampFactory\ElfCampFactory等 | 实现抽象工厂, 创建对应阵营的整套产品 |
客户端(Client) | PlayerEquipManager | 调用抽象工厂创建产品, 不关心具体实现 |
- 定义抽象产品(接口)
先定义每个”产品类型”的接口, 规定产品的核心功能(比如武器能攻击\防具能加防御\坐骑能召唤)
- 实现具体产品(阵营装备)
为每个阵营创建具体的装备, 实现对应的抽象产品接口. 这些装备可以是Unity中的Monobehaviour(挂载在预制体上), 也可以是纯逻辑类(根据需求选择).
这里我们用”逻辑 + 预制体绑定”的方式, 更贴合Unity开发:
- 定义抽象工厂(ICampFactory)
抽象工厂接口定义”创建一整套产品家族”的方法 ——— 每个产品类型对应一个创建方法(创建武器\创建防具\创建坐骑).
- 实现具体工厂(阵营工厂)
每个阵营对应一个具体工厂, 实现抽象工厂的方法, 负责创建该阵营的整套装备. 这里关键是”绑定预制体” ——— 在Unity编辑器中给工厂赋值对应阵营的装备预制体, 工厂通过实例化预制体来创建产品.
注: 用 ScriptableObject 做具体工厂, 是Unity中的最佳实践 ——— 可以在编辑器中可视化配置预制体, 不用挂载在游戏对象上, 方便管理和复用
- 客户端试用(PlayerEquipManager)
客户端(玩家装备管理器) 只依赖抽象工厂 ICampFactory, 不关心具体哪个阵营的工厂. 通过切换不同的具体工厂, 就能一键切换整套装备家族.
Unity 中实际操作(可视化配置)
- 创建装备预制体:
- 新建 9 个预制体(人类:剑、铁甲、战马;精灵:弓、皮甲、巨鹿;兽人:斧、石甲、战猪);
- 给每个预制体挂载对应的具体产品脚本(如剑预制体挂载
Sword脚本)。
- 创建具体工厂资产:
- 在 Project 窗口右键 → Game → Factories → 分别创建 HumanCampFactory、ElfCampFactory、OrcCampFactory 资产;
- 选中每个工厂资产,在 Inspector 中赋值对应的装备预制体(如人类工厂的 swordPrefab 拖入剑预制体)。
- 配置玩家对象:
- 创建 Player 游戏对象,添加
PlayerEquipManager脚本; - 在 Player 下创建两个空对象(WeaponPoint、ArmorPoint),作为武器和防具的挂载点;
- 在场景中创建 MountLayer 空对象,作为坐骑的父对象;
- 给
PlayerEquipManager的currentCampFactory赋值任意工厂(如人类工厂)。
- 创建切换阵营按钮:
- 在 UI 中创建 3 个按钮(人类、精灵、兽人);
- 给每个按钮绑定
OnClick事件,调用PlayerEquipManager的对应切换方法,并传入对应的工厂资产(如人类按钮传入 HumanCampFactory 资产)。
- 运行测试:
- 启动游戏,玩家会自动装备当前工厂的整套装备;
- 点击不同阵营按钮,玩家会一键切换整套装备(武器、防具、坐骑同步变化),控制台输出对应效果。
抽象工厂模式的核心优点
- 产品家族一致性:同一工厂创建的产品(如人类的剑、铁甲、战马)天然配套,不会出现 “精灵的弓配人类的铁甲” 这种混乱情况。
- 解耦创建与使用:客户端(PlayerEquipManager)只关心 “装备功能”(攻击、装备、召唤),不关心装备是怎么创建的(预制体实例化、属性赋值)。
- 扩展灵活:新增阵营(如矮人)只需做 3 件事:
- 实现矮人对应的 3 个具体产品(矮人锤、矮人甲、矮人机甲);
- 创建
DwarfCampFactory实现ICampFactory,赋值矮人装备预制体; - 新增切换按钮,绑定矮人工厂。无需修改任何现有代码(符合开放 / 封闭原则)。
- 便于管理:所有阵营的装备创建逻辑集中在对应工厂,预制体配置可视化,Unity 编辑器中易于维护。
Unity中的适用场景
- 阵营 / 主题系统: 如本例的阵营装备\不同主题的UI组件(如科幻风\古风\魔幻风的按钮\面板\图标).
- 敌人套装系统: 不同类型的敌人(普通怪\精英怪\BOSS)有对应的攻击方式\技能\凋落物, 用抽象工厂创建”敌人套装”
- 场景道具系统: 不同场景(森林\沙漠\雪地)的树木\岩石\地面装饰, 用抽象工厂创建”场景道具家族”.
- 角色养成系统: 不同职业(战士\法师\射手)的技能\武器\天赋, 用抽象工厂创建”职业套装”.
抽象工厂模式的注意事项
- 产品家族稳定时更适用: 如果需要频繁新增”产品类型”(比如除了了武器\防具\坐骑, 还要加”饰品”), 则需要修改抽象接口(加 CreateAccessory 方法)和所有具体工厂, 成本较高.
- 避免过渡设计: 如果产品之间没有依赖关系(比如武器和坐骑互不相关), 则无需用抽象工厂, 直接用更简单工厂或工厂方法模式即可.
- ScriptableObject 替代单例工厂: Unity中用 ScriptableObject 做具体工厂, 比单例脚本更灵活(可创建多个实例\支持序列化).
总结
抽象工厂模式的核心是”批量创建配套产品家族”. 在Unity中, 它通过”抽象工厂接口 = 具体工厂(ScriptableObject) + 抽象产品接口 + 具体产品(预制体 + 脚本)”的组合, 完美解决了 “相关产品配套创建” 和 “扩展困难” 的问题.
比如后续要做 “科幻阵营”, 只需新增科幻装备预制体\科幻工厂, 客户端一键切换就能获得整套科幻装备, 不用改动原有代码 ——— 这就是抽象工厂模式在 Unity 中最强大的价值.