抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
问题定义
场景:跨平台UI组件
# ❌ 问题:客户端代码依赖具体类
class WindowsButton:
def render(self):
return "Windows按钮"
class WindowsCheckbox:
def render(self):
return "Windows复选框"
class MacButton:
def render(self):
return "Mac按钮"
class MacCheckbox:
def render(self):
return "Mac复选框"
# 客户端代码
def create_ui(os_type):
if os_type == "windows":
button = WindowsButton()
checkbox = WindowsCheckbox()
elif os_type == "mac":
button = MacButton()
checkbox = MacCheckbox()
button.render()
checkbox.render()
问题: - 客户端需要知道所有具体类 - 添加新组件类型需要修改客户端代码 - 组件不匹配的风险(Windows按钮 + Mac复选框)
场景:不同数据库的产品族
# MySQL相关类
class MySQLConnection:
def connect(self):
print("连接MySQL")
class MySQLQuery:
def execute(self):
print("MySQL查询")
# PostgreSQL相关类
class PostgreSQLConnection:
def connect(self):
print("连接PostgreSQL")
class PostgreSQLQuery:
def execute(self):
print("PostgreSQL查询")
# 问题:可能创建不匹配的组合
def create_database(db_type):
if db_type == "mysql":
conn = MySQLConnection()
query = PostgreSQLQuery() # ❌ 不匹配!
elif db_type == "postgresql":
conn = PostgreSQLConnection()
query = MySQLQuery() # ❌ 不匹配!
conn.connect()
query.execute()
解决方案
抽象工厂模式提供一个接口,用于创建相关对象的家族,确保产品的一致性。
classDiagram
class AbstractFactory {
<>
+createProductA() ProductA
+createProductB() ProductB
}
class ConcreteFactory1 {
+createProductA() ProductA
+createProductB() ProductB
}
class ConcreteFactory2 {
+createProductA() ProductA
+createProductB() ProductB
}
class AbstractProductA {
<>
+operation()
}
class AbstractProductB {
<>
+operation()
}
class ProductA1 {
+operation()
}
class ProductB1 {
+operation()
}
class ProductA2 {
+operation()
}
class ProductB2 {
+operation()
}
AbstractFactory <|-- ConcreteFactory1
AbstractFactory <|-- ConcreteFactory2
AbstractProductA <|-- ProductA1
AbstractProductA <|-- ProductA2
AbstractProductB <|-- ProductB1
AbstractProductB <|-- ProductB2
ConcreteFactory1 ..> ProductA1 : creates
ConcreteFactory1 ..> ProductB1 : creates
ConcreteFactory2 ..> ProductA2 : creates
ConcreteFactory2 ..> ProductB2 : creates
标准实现
抽象产品
from abc import ABC, abstractmethod
class Button(ABC):
"""按钮抽象类"""
@abstractmethod
def render(self):
pass
class Checkbox(ABC):
"""复选框抽象类"""
@abstractmethod
def render(self):
pass
具体产品
# Windows产品族
class WindowsButton(Button):
def render(self):
print("渲染Windows按钮(灰色、圆角)")
class WindowsCheckbox(Checkbox):
def render(self):
print("渲染Windows复选框(方形)")
# Mac产品族
class MacButton(Button):
def render(self):
print("渲染Mac按钮(蓝色、圆角更大)")
class MacCheckbox(Checkbox):
def render(self):
print("渲染Mac复选框(圆形)")
# Linux产品族
class LinuxButton(Button):
def render(self):
print("渲染Linux按钮(简洁、主题色)")
class LinuxCheckbox(Checkbox):
def render(self):
print("渲染Linux复选框(方形、扁平化)")
抽象工厂
class GUIFactory(ABC):
"""GUI工厂抽象类"""
@abstractmethod
def create_button(self) -> Button:
pass
@abstractmethod
def create_checkbox(self) -> Checkbox:
pass
具体工厂
class WindowsFactory(GUIFactory):
"""Windows工厂 - 创建Windows产品族"""
def create_button(self) -> Button:
return WindowsButton()
def create_checkbox(self) -> Checkbox:
return WindowsCheckbox()
class MacFactory(GUIFactory):
"""Mac工厂 - 创建Mac产品族"""
def create_button(self) -> Button:
return MacButton()
def create_checkbox(self) -> Checkbox:
return MacCheckbox()
class LinuxFactory(GUIFactory):
"""Linux工厂 - 创建Linux产品族"""
def create_button(self) -> Button:
return LinuxButton()
def create_checkbox(self) -> Checkbox:
return LinuxCheckbox()
客户端使用
def render_ui(factory: GUIFactory):
"""渲染UI - 客户端不依赖具体类"""
button = factory.create_button()
checkbox = factory.create_checkbox()
button.render()
checkbox.render()
# 使用不同工厂
print("Windows UI:")
render_ui(WindowsFactory())
print()
print("Mac UI:")
render_ui(MacFactory())
print()
print("Linux UI:")
render_ui(LinuxFactory())
实战应用
应用1:跨平台数据库访问
from abc import ABC, abstractmethod
# 抽象产品
class DatabaseConnection(ABC):
"""数据库连接抽象类"""
@abstractmethod
def connect(self):
pass
@abstractmethod
def disconnect(self):
pass
class DatabaseCommand(ABC):
"""数据库命令抽象类"""
@abstractmethod
def execute(self, sql):
pass
class DatabaseTransaction(ABC):
"""数据库事务抽象类"""
@abstractmethod
def begin(self):
pass
@abstractmethod
def commit(self):
pass
@abstractmethod
def rollback(self):
pass
# MySQL产品族
class MySQLConnection(DatabaseConnection):
def connect(self):
print("MySQL连接已建立")
def disconnect(self):
print("MySQL连接已关闭")
class MySQLCommand(DatabaseCommand):
def execute(self, sql):
print(f"MySQL执行: {sql}")
class MySQLTransaction(DatabaseTransaction):
def begin(self):
print("MySQL事务开始")
def commit(self):
print("MySQL事务提交")
def rollback(self):
print("MySQL事务回滚")
# PostgreSQL产品族
class PostgreSQLConnection(DatabaseConnection):
def connect(self):
print("PostgreSQL连接已建立")
def disconnect(self):
print("PostgreSQL连接已关闭")
class PostgreSQLCommand(DatabaseCommand):
def execute(self, sql):
print(f"PostgreSQL执行: {sql}")
class PostgreSQLTransaction(DatabaseTransaction):
def begin(self):
print("PostgreSQL事务开始")
def commit(self):
print("PostgreSQL事务提交")
def rollback(self):
print("PostgreSQL事务回滚")
# 抽象工厂
class DatabaseFactory(ABC):
"""数据库工厂抽象类"""
@abstractmethod
def create_connection(self) -> DatabaseConnection:
pass
@abstractmethod
def create_command(self) -> DatabaseCommand:
pass
@abstractmethod
def create_transaction(self) -> DatabaseTransaction:
pass
# 具体工厂
class MySQLFactory(DatabaseFactory):
def create_connection(self) -> DatabaseConnection:
return MySQLConnection()
def create_command(self) -> DatabaseCommand:
return MySQLCommand()
def create_transaction(self) -> DatabaseTransaction:
return MySQLTransaction()
class PostgreSQLFactory(DatabaseFactory):
def create_connection(self) -> DatabaseConnection:
return PostgreSQLConnection()
def create_command(self) -> DatabaseCommand:
return PostgreSQLCommand()
def create_transaction(self) -> DatabaseTransaction:
return PostgreSQLTransaction()
# 使用
def use_database(factory: DatabaseFactory):
"""使用数据库"""
conn = factory.create_connection()
cmd = factory.create_command()
txn = factory.create_transaction()
conn.connect()
txn.begin()
cmd.execute("SELECT * FROM users")
txn.commit()
conn.disconnect()
print("使用MySQL:")
use_database(MySQLFactory())
print()
print("使用PostgreSQL:")
use_database(PostgreSQLFactory())
应用2:电商主题
from abc import ABC, abstractmethod
# 抽象产品
class ThemeColors(ABC):
"""主题颜色"""
@abstractmethod
def primary(self):
pass
@abstractmethod
def secondary(self):
pass
@abstractmethod
def background(self):
pass
class ThemeFont(ABC):
"""主题字体"""
@abstractmethod
def heading(self):
pass
@abstractmethod
def body(self):
pass
class ThemeIcon(ABC):
"""主题图标"""
@abstractmethod
def shopping_cart(self):
pass
@abstractmethod
def search(self):
pass
# 暗色主题产品族
class DarkThemeColors(ThemeColors):
def primary(self):
return "#3b82f6" # 蓝色
def secondary(self):
return "#8b5cf6" # 紫色
def background(self):
return "#1f2937" # 深灰
class DarkThemeFont(ThemeFont):
def heading(self):
return "Arial Bold 24px"
def body(self):
return "Arial 16px"
class DarkThemeIcon(ThemeIcon):
def shopping_cart(self):
return "🛒-white"
def search(self):
return "🔍-white"
# 亮色主题产品族
class LightThemeColors(ThemeColors):
def primary(self):
return "#2563eb" # 蓝色
def secondary(self):
return "#7c3aed" # 紫色
def background(self):
return "#ffffff" # 白色
class LightThemeFont(ThemeFont):
def heading(self):
return "Helvetica Bold 24px"
def body(self):
return "Helvetica 16px"
class LightThemeIcon(ThemeIcon):
def shopping_cart(self):
return "🛒-black"
def search(self):
return "🔍-black"
# 抽象工厂
class ThemeFactory(ABC):
"""主题工厂抽象类"""
@abstractmethod
def create_colors(self) -> ThemeColors:
pass
@abstractmethod
def create_font(self) -> ThemeFont:
pass
@abstractmethod
def create_icon(self) -> ThemeIcon:
pass
# 具体工厂
class DarkThemeFactory(ThemeFactory):
def create_colors(self) -> ThemeColors:
return DarkThemeColors()
def create_font(self) -> ThemeFont:
return DarkThemeFont()
def create_icon(self) -> ThemeIcon:
return DarkThemeIcon()
class LightThemeFactory(ThemeFactory):
def create_colors(self) -> ThemeColors:
return LightThemeColors()
def create_font(self) -> ThemeFont:
return LightThemeFont()
def create_icon(self) -> ThemeIcon:
return LightThemeIcon()
# 使用
def apply_theme(factory: ThemeFactory):
"""应用主题"""
colors = factory.create_colors()
font = factory.create_font()
icon = factory.create_icon()
print(f"主色: {colors.primary()}")
print(f"副色: {colors.secondary()}")
print(f"背景: {colors.background()}")
print(f"标题字体: {font.heading()}")
print(f"正文字体: {font.body()}")
print(f"购物车图标: {icon.shopping_cart()}")
print(f"搜索图标: {icon.search()}")
print("暗色主题:")
apply_theme(DarkThemeFactory())
print()
print("亮色主题:")
apply_theme(LightThemeFactory())
应用3:游戏装备套装
from abc import ABC, abstractmethod
# 抽象产品
class Weapon(ABC):
"""武器"""
@abstractmethod
def attack(self):
pass
class Armor(ABC):
"""护甲"""
@abstractmethod
def defense(self):
pass
class Mount(ABC):
"""坐骑"""
@abstractmethod
def speed(self):
pass
# 战士套装
class Sword(Weapon):
def attack(self):
return 100
class PlateArmor(Armor):
def defense(self):
return 80
class Horse(Mount):
def speed(self):
return 50
# 法师套装
class Staff(Weapon):
def attack(self):
return 150
class RobeArmor(Armor):
def defense(self):
return 30
class Dragon(Mount):
def speed(self):
return 200
# 弓箭手套装
class Bow(Weapon):
def attack(self):
return 120
class LeatherArmor(Armor):
def defense(self):
return 50
class Eagle(Mount):
def speed(self):
return 100
# 抽象工厂
class EquipmentFactory(ABC):
"""装备工厂抽象类"""
@abstractmethod
def create_weapon(self) -> Weapon:
pass
@abstractmethod
def create_armor(self) -> Armor:
pass
@abstractmethod
def create_mount(self) -> Mount:
pass
# 具体工厂
class WarriorFactory(EquipmentFactory):
def create_weapon(self) -> Weapon:
return Sword()
def create_armor(self) -> Armor:
return PlateArmor()
def create_mount(self) -> Mount:
return Horse()
class MageFactory(EquipmentFactory):
def create_weapon(self) -> Weapon:
return Staff()
def create_armor(self) -> Armor:
return RobeArmor()
def create_mount(self) -> Mount:
return Dragon()
class ArcherFactory(EquipmentFactory):
def create_weapon(self) -> Weapon:
return Bow()
def create_armor(self) -> Armor:
return LeatherArmor()
def create_mount(self) -> Mount:
return Eagle()
# 使用
def equip_character(factory: EquipmentFactory):
"""装备角色"""
weapon = factory.create_weapon()
armor = factory.create_armor()
mount = factory.create_mount()
print(f"攻击力: {weapon.attack()}")
print(f"防御力: {armor.defense()}")
print(f"速度: {mount.speed()}")
print("战士装备:")
equip_character(WarriorFactory())
print()
print("法师装备:")
equip_character(MageFactory())
print()
print("弓箭手装备:")
equip_character(ArcherFactory())
工厂方法 vs 抽象工厂
| 维度 | 工厂方法 | 抽象工厂 |
|---|---|---|
| 创建对象 | 单一产品 | 产品族 |
| 工厂数量 | 每个产品一个工厂 | 每个产品族一个工厂 |
| 复杂度 | 较低 | 较高 |
| 一致性 | 不保证 | 保证产品族一致性 |
graph TB
A[创建型模式] --> B[工厂方法]
A --> C[抽象工厂]
B --> B1[创建单一产品]
B --> B2[一个产品一个工厂]
C --> C1[创建产品族]
C --> C2[一个家族一个工厂]
style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px
style B fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
style C fill:#fff9c4,stroke:#f9a825,stroke-width:2px
优缺点
✅ 优点
| 优点 | 说明 |
|---|---|
| 产品族一致性 | 确保产品族内的产品匹配 |
| 解耦客户端 | 客户端不依赖具体类 |
| 易于扩展 | 新增产品族无需修改客户端 |
| 代码复用 | 产品族的创建逻辑复用 |
❌ 缺点
| 缺点 | 说明 |
|---|---|
| 类数量多 | 抽象产品 + 具体产品 + 抽象工厂 + 具体工厂 |
| 复杂度高 | 比工厂方法更复杂 |
| 扩展产品难 | 新增产品类型需要修改所有工厂 |
与其他模式的关系
| 模式 | 关系 |
|---|---|
| 工厂方法 | 抽象工厂的工厂方法通常用工厂方法实现 |
| 单例 | 工厂可以是单例 |
| 原型 | 抽象工厂可以用原型创建对象 |
本章要点
- ✅ 抽象工厂创建相关对象的家族
- ✅ 确保产品族内的产品匹配
- ✅ 客户端只依赖抽象工厂和抽象产品
- ✅ 新增产品族容易,新增产品类型困难
- ✅ 适用于需要创建多个相关对象的场景
恭喜完成创建型模式部分!
下一步:适配器模式 开始学习结构型模式 🚀