一、工厂方法 vs 抽象工厂(类比一维 vs 二维数组)
- 工厂方法模式:适用于单一维度的产品分类,比如只根据角色类型(战士/法师)决定其武器。
- 抽象工厂模式:适用于多个维度的产品分类,比如不仅区分角色类型,还要区分装备类型(武器/防具),每个装备类型又有具体实现(剑/法杖,盾/魔法书)。
类比:
- 工厂方法 ≈ 一维数组(单分类维度)
- 抽象工厂 ≈ 二维数组(多分类维度)
二、抽象工厂模式的核心思想
当一个系统需要创建一系列相关或依赖的对象,且这些对象属于多个维度/类别时,使用抽象工厂模式能更好地组织代码,提高模块化和扩展性。
三、以RPG游戏装备为例理解抽象工厂模式
1. 场景描述
- 游戏角色有不同职业:战士、法师
- 每个角色有不同装备:武器、防具
- 武器与防具是两个维度
- 维度1:装备类型(武器 / 防具)
- 维度2:具体种类(剑/法杖;盾/魔法书)
2. 设计要素拆解
(1) 抽象产品(Abstract Products)
- 定义产品接口,约定具体产品必须实现的功能
Weapon(武器):纯虚类,约定使用()方法Armor(防具):纯虚类,约定装备()方法
(2) 具体产品(Concrete Products)
- 实现抽象产品接口,是最终被使用的对象
- 剑(Sword)、盾牌(Shield)→ 战士装备
- 法杖(Staff)、魔法书(Spellbook)→ 法师装备
(3) 抽象工厂(Abstract Factory)
- 定义一组创建产品的接口方法,每个方法对应创建某一类产品
createWeapon()→ 返回 Weapon 类型createArmor()→ 返回 Armor 类型
抽象工厂不关心具体实现,只定义“我要能生产这一类产品的能力”
(4) 具体工厂(Concrete Factories)
- 实现抽象工厂接口,负责实例化具体的产品组合
WarriorFactory:创建剑 + 盾牌MageFactory:创建法杖 + 魔法书
3. 客户端代码(游戏逻辑)
- 游戏角色在构造时传入一个装备工厂对象
- 在需要装备时,通过工厂提供的接口创建武器和防具,并调用其功能方法
- 如:
weapon->使用(),armor->装备()
- 如:
客户端无需关心具体是哪种武器或防具,也无需了解它们的实现细节,只需与抽象工厂和抽象产品交互。
四、抽象工厂模式的构成要素
| 要素 | 说明 | 示例 |
|---|---|---|
| 抽象产品(Abstract Product) | 定义产品的接口,如 Weapon、Armor | 约定武器必须能“使用”,防具必须能“装备” |
| 具体产品(Concrete Product) | 实现抽象产品接口的具体类 | 剑、法杖、盾牌、魔法书 |
| 抽象工厂(Abstract Factory) | 定义创建一整套相关产品的方法接口 | 提供 createWeapon() 和 createArmor() |
| 具体工厂(Concrete Factory) | 实现抽象工厂,负责实例化某一类产品组合 | 战士工厂生产剑+盾,法师工厂生产法杖+魔法书 |
五、抽象工厂模式的优劣
优势:
- 多维度定制:支持多个产品维度的组合,每一种组合都可以通过不同的具体工厂实现
- 高内聚低耦合:客户端只与抽象工厂和抽象产品交互,不依赖具体实现
- 统一管理产品族:确保创建的产品之间是协同工作的(如武器和防具属于同一角色体系)
- 符合开闭原则:新增产品维度或类型时,可通过扩展而非修改现有代码实现
劣势:
- 类数量增多:每增加一个产品维度或类型,都需要新增对应的抽象和具体类,导致类爆炸
- 复杂性高:多层抽象使得代码结构较复杂,理解和维护难度增加
- 灵活性降低:产品通常是“配套”的(如剑配盾),单独替换某一类产品较困难
- 抽象与耦合并存:虽然解耦了客户端与具体实现,但产品之间通常是紧耦合的(必须配套使用)
六、抽象工厂模式的典型应用场景
-
跨平台 GUI 框架
- 如 Qt、Cute 等需要在 Windows、macOS、Linux 上提供统一的按钮、文本框、对话框等 UI 组件
- 每个平台是一套工厂,生产对应风格的组件
-
游戏引擎 文件系统
- 不同操作系统(Windows/Linux/Android)的文件 API 不同
- 抽象出统一的读写接口,通过不同工厂创建对应的 Reader/Writer
-
UI 主题切换
- 游戏或应用支持多种界面主题(如暗黑/明亮风格)
- 通过抽象工厂生产同一套风格下的按钮、菜单等组件
-
图形渲染后端(RHI - Render Hardware Interface)
- 抽象纹理、着色器、缓冲区等通用概念
- 支持在不同平台/图形API(如DirectX、OpenGL、Vulkan)间切换渲染后端
-
跨平台网络库
- 客户端可能运行在 Windows/Android,服务端在 Linux
- 抽象出统一的网络接口,通过工厂创建平台相关实现
七、抽象工厂模式 vs 工厂方法模式
| 对比维度 | 工厂方法模式 | 抽象工厂模式 |
|---|---|---|
| 产品维度 | 单一维度 | 多个维度 |
| 核心目标 | 定义一个创建单一产品的接口 | 定义一组创建相关产品族的接口 |
| 复杂度 | 较低,容易扩展单一产品类型 | 较高,需管理多个产品及其组合 |
| 适用场景 | 产品种类单一,比如只生产武器 | 产品种类多且有关联,比如武器+防具 |
| 扩展性 | 易于扩展新产品类型 | 扩展新维度较复杂,需要新增工厂和产品类 |
抽象工厂可以看作是工厂方法模式在多维度产品创建场景下的扩展和进阶。
- 抽象工厂模式适用于需要创建多个相关或依赖的、多维度分类的产品对象的场景
- 核心在于定义一整套产品族的创建接口,并由具体工厂负责实例化某一组具体产品
- 优点是结构清晰、职责分明、支持多维度定制、符合开闭原则
- 缺点是类数量较多、结构复杂、产品之间通常耦合度高
- 在实际项目中广泛应用于跨平台UI组件、游戏引擎、图形渲染、主题系统、网络通信等模块的抽象与实现
1709

被折叠的 条评论
为什么被折叠?



