抽象工厂模式 (Abstract Factory Pattern)

概述
抽象工厂模式是一种创建型设计模式,它提供了一个接口用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。
通俗理解:想象你要买电子设备,苹果工厂只生产苹果产品(iPhone + MacBook),小米工厂只生产小米产品(小米手机 + 小米笔记本)。每个工厂生产的产品都是同一个品牌的"全家桶",产品之间可以完美协同工作。
核心概念
为什么需要抽象工厂?
在现实生活中,我们经常需要购买一整套相关的产品:
🍎 苹果生态:iPhone + MacBook + AirPods(无缝协同)
📱 小米生态:小米手机 + 小米笔记本 + 小米耳机(互联互通)
🎮 游戏生态:PlayStation + 手柄 + 游戏光盘(完美适配)
如果你混搭不同品牌的产品,可能会遇到兼容性问题。抽象工厂模式就是为了解决这个问题。
产品族 vs 产品等级结构
产品等级结构:同类产品的继承层次
手机 → iPhone、小米手机、华为手机
笔记本 → MacBook、小米笔记本、华为笔记本
产品族:不同产品等级结构中相关的产品组合
苹果产品族:iPhone + MacBook
小米产品族:小米手机 + 小米笔记本
模式结构
抽象工厂模式包含以下几个角色:
抽象产品 (Abstract Product): 定义产品的接口(如Phone、Laptop)
具体产品 (Concrete Product): 实现抽象产品接口的具体类(如iPhone、MacBook)
抽象工厂 (Abstract Factory): 定义创建产品族的接口
具体工厂 (Concrete Factory): 实现抽象工厂,创建具体的产品族
客户端 (Client): 使用抽象工厂和抽象产品接口
与其他工厂模式的比较
特性 | 简单工厂 | 工厂方法 | 抽象工厂 |
产品数量 | 单一产品 | 单一产品 | 产品族 |
工厂数量 | 一个 | 多个 | 多个 |
扩展方式 | 修改工厂 | 增加工厂 | 增加工厂族 |
复杂度 | 低 | 中 | 高 |
使用场景 | 产品少且固定 | 产品种类需扩展 | 产品族需整体切换 |
代码示例说明
1. 抽象产品接口
// 手机接口 - 抽象产品A
type Phone interface {
Call(number string)
GetModel() string
GetBrand() string
ShowSpecs()
}
// 笔记本电脑接口 - 抽象产品B
type Laptop interface {
PowerOn()
GetModel() string
GetBrand() string
ConnectToPhone(phone Phone) string // 关键:与手机协同工作
}
重点:ConnectToPhone
方法体现了产品族内产品的相关性 - 同品牌设备连接更完美!
2. 苹果产品族实现
// 苹果手机 - 具体产品A1
type iPhone struct {
model string
brand string
}
func (p *iPhone) Call(number string) {
fmt.Printf("📱 %s拨打电话到 %s (使用FaceTime音频)\n", p.model, number)
}
func (p *iPhone) ShowSpecs() {
fmt.Printf("📱 %s规格: A17处理器, iOS系统, 支持5G\n", p.model)
}
// 苹果笔记本 - 具体产品B1
type MacBook struct {
model string
brand string
}
func (m *MacBook) ConnectToPhone(phone Phone) string {
if phone.GetBrand() == m.brand {
return fmt.Sprintf("🔗 %s与%s完美连接 - 支持连续互通、AirDrop、通用剪贴板",
m.model, phone.GetModel())
}
return fmt.Sprintf("⚠️ %s与%s连接受限 - 仅支持基础蓝牙功能",
m.model, phone.GetModel())
}
核心思想:同品牌产品有特殊的协同功能,跨品牌则功能受限。
3. 小米产品族实现
// 小米手机 - 具体产品A2
type XiaomiPhone struct {
model string
brand string
}
func (p *XiaomiPhone) Call(number string) {
fmt.Printf("📱 %s拨打电话到 %s (使用小米通话)\n", p.model, number)
}
// 小米笔记本 - 具体产品B2
type XiaomiLaptop struct {
model string
brand string
}
func (m *XiaomiLaptop) ConnectToPhone(phone Phone) string {
if phone.GetBrand() == m.brand {
return fmt.Sprintf("🔗 %s与%s完美连接 - 支持小米互传、多屏协同、文件共享",
m.model, phone.GetModel())
}
return fmt.Sprintf("⚠️ %s与%s连接受限 - 仅支持基础蓝牙功能",
m.model, phone.GetModel())
}
4. 抽象工厂接口
// 电子设备工厂接口
type ElectronicsFactory interface {
CreatePhone() Phone // 创建手机
CreateLaptop() Laptop // 创建笔记本
GetBrandName() string // 获取品牌名
}
设计要点:一个工厂负责创建整个产品族,确保产品间的兼容性。
5. 具体工厂实现
// 苹果工厂 - 只生产苹果产品族
type AppleFactory struct{}
func (f *AppleFactory) CreatePhone() Phone {
return &iPhone{
model: "iPhone 15 Pro",
brand: "Apple",
}
}
func (f *AppleFactory) CreateLaptop() Laptop {
return &MacBook{
model: "MacBook Pro M3",
brand: "Apple",
}
}
// 小米工厂 - 只生产小米产品族
type XiaomiFactory struct{}
func (f *XiaomiFactory) CreatePhone() Phone {
return &XiaomiPhone{
model: "小米14 Pro",
brand: "Xiaomi",
}
}
func (f *XiaomiFactory) CreateLaptop() Laptop {
return &XiaomiLaptop{
model: "小米笔记本Pro",
brand: "Xiaomi",
}
}
6. 设备套装类
// 电子设备套装 - 体现产品族的完整性
type DeviceBundle struct {
phone Phone
laptop Laptop
brand string
}
func NewDeviceBundle(factory ElectronicsFactory) *DeviceBundle {
return &DeviceBundle{
phone: factory.CreatePhone(), // 同一工厂创建
laptop: factory.CreateLaptop(), // 确保兼容性
brand: factory.GetBrandName(),
}
}
func (db *DeviceBundle) ShowBundle() {
fmt.Printf("\n📦 === %s全家桶套装 ===\n", db.brand)
fmt.Printf("📱 手机: %s\n", db.phone.GetModel())
fmt.Printf("💻 笔记本: %s\n", db.laptop.GetModel())
// 展示生态协同优势
connectionResult := db.laptop.ConnectToPhone(db.phone)
fmt.Printf("🔗 生态协同: %s\n", connectionResult)
}
7. 客户端使用
func main() {
// 创建不同品牌的工厂
appleFactory := NewAppleFactory()
xiaomiFactory := NewXiaomiFactory()
// 创建品牌生态套装
appleBundle := NewDeviceBundle(appleFactory) // 苹果全家桶
xiaomiBundle := NewDeviceBundle(xiaomiFactory) // 小米全家桶
appleBundle.ShowBundle()
xiaomiBundle.ShowBundle()
// 演示跨品牌混搭的问题
fmt.Println("\n⚠️ === 混搭不同品牌的问题演示 ===")
applePhone := appleFactory.CreatePhone()
xiaomiLaptop := xiaomiFactory.CreateLaptop()
connectionResult := xiaomiLaptop.ConnectToPhone(applePhone)
fmt.Printf("🔗 跨品牌连接: %s\n", connectionResult)
fmt.Println("💡 这就是为什么我们需要抽象工厂来确保产品族的一致性!")
}
运行示例
运行 abstract_factory.go
文件:
go run abstract_factory.go
输出结果:
🎯 === 抽象工厂模式 - 电子设备品牌工厂 ===
🏭 === Apple设备使用演示 ===
📱 iPhone 15 Pro规格: A17处理器, iOS系统, 支持5G
📱 iPhone 15 Pro拨打电话到 13888888888 (使用FaceTime音频)
💻 MacBook Pro M3开机 (苹果开机音效)
🔄 设备协同测试:
🔗 MacBook Pro M3与iPhone 15 Pro完美连接 - 支持连续互通、AirDrop、通用剪贴板
🏭 === Xiaomi设备使用演示 ===
📱 小米14 Pro规格: 骁龙处理器, MIUI系统, 支持5G
📱 小米14 Pro拨打电话到 13888888888 (使用小米通话)
💻 小米笔记本Pro开机 (小米开机动画)
🔄 设备协同测试:
🔗 小米笔记本Pro与小米14 Pro完美连接 - 支持小米互传、多屏协同、文件共享
==================================================
📦 === Apple全家桶套装 ===
📱 手机: iPhone 15 Pro
💻 笔记本: MacBook Pro M3
🔗 生态协同: 🔗 MacBook Pro M3与iPhone 15 Pro完美连接 - 支持连续互通、AirDrop、通用剪贴板
📦 === Xiaomi全家桶套装 ===
📱 手机: 小米14 Pro
💻 笔记本: 小米笔记本Pro
🔗 生态协同: 🔗 小米笔记本Pro与小米14 Pro完美连接 - 支持小米互传、多屏协同、文件共享
==================================================
⚠️ === 混搭不同品牌的问题演示 ===
📱 设备: iPhone 15 Pro
💻 设备: 小米笔记本Pro
🔗 跨品牌连接: ⚠️ 小米笔记本Pro与iPhone 15 Pro连接受限 - 仅支持基础蓝牙功能
💡 这就是为什么我们需要抽象工厂来确保产品族的一致性!
优点
🔐 确保产品族的一致性:同一工厂创建的产品保证兼容
🔄 符合开闭原则:添加新品牌时无需修改现有代码
🎯 分离了具体类:客户端只依赖抽象接口
⚡ 易于切换产品族:只需更换工厂即可切换整个品牌生态
缺点
📈 增加了系统复杂性:需要定义大量的类和接口
🔧 扩展困难:添加新产品类型需要修改所有工厂接口
📊 类数量增加:每个产品族都需要相应的类
设计原则体现
🎯 依赖倒置原则:高层模块依赖抽象工厂接口
🔓 开闭原则:对扩展开放(新增品牌),对修改关闭
🔄 里氏替换原则:不同品牌工厂可以互相替换
📋 单一职责原则:每个工厂只负责一个品牌的产品族
与其他模式的区别
vs 建造者模式
特性 | 抽象工厂模式 | 建造者模式 |
目的 | 创建产品族 | 创建复杂对象 |
侧重点 | 产品的组合 | 产品的构造过程 |
产品关系 | 相关产品族 | 单一复杂产品 |
vs 工厂方法模式
特性 | 抽象工厂模式 | 工厂方法模式 |
产品数量 | 多个相关产品 | 单个产品 |
工厂职责 | 创建产品族 | 创建单一产品 |
扩展方式 | 增加整个产品族 | 增加单个产品类型 |
记忆口诀
"一个工厂一个牌,全家桶里不混搭"
一个工厂 = 一个品牌
全家桶 = 产品族(相关产品的组合)
不混搭 = 确保产品族的一致性
总结
抽象工厂模式就像现实中的品牌专卖店:
🍎 苹果店:只卖苹果产品,产品间无缝协同
📱 小米店:只卖小米产品,生态互联互通
🎮 索尼店:只卖索尼产品,完美适配
当你需要确保一套产品风格统一、功能协同时,抽象工厂模式是最佳选择。它虽然增加了代码复杂性,但换来了产品族的一致性和系统的可扩展性。
Subscribe to my newsletter
Read articles from shaojie li directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

shaojie li
shaojie li
Hi there 👋, I'm [mamba] I'm a Speech Recognition Engineer with a passion for machine learning and natural language processing. I love working on impactful projects and am always looking for new challenges.