如果说昨天的工厂方法是针对单个产品(比如只生产卡车),那么今天的抽象工厂就是针对产品族(比如生产一整套豪华汽车组件,包括豪华车轮、豪华方向盘)。

Day 3:抽象工厂模式 (Abstract Factory Pattern)

1. 它是怎么来的?

想象一下,你正在开发一款跨平台的 UI 工具包(支持 Windows 和 Mac)。
UI 组件有很多种:按钮(Button)、复选框(Checkbox)、文本框(TextField)。

如果你用昨天的工厂方法,你得写一个 ButtonFactory、一个 CheckboxFactory。
但这里有一个致命的隐患:你必须确保 Windows 系统上创建的按钮和复选框都是 Windows 风格的,绝对不能在 Mac 系统里误用了一个 Windows 风格的按钮。

这就引入了“产品族”的概念。Windows 的按钮和 Windows 的复选框属于同一个产品族;Mac 的按钮和 Mac 的复选框属于另一个产品族。

抽象工厂模式就是为了解决“一系列相互依赖的产品的创建问题”而诞生的:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

2. 适用场景

  • 产品族群:系统需要由多个相关联的产品对象组成,且它们必须配套使用。
  • 跨平台/多主题切换:如支持多种操作系统界面(Windows/macOS/Linux)、更换软件皮肤主题(暗黑模式/明亮模式)。
  • 解耦依赖:客户端不应该依赖具体产品的创建细节,只通过高度抽象的接口与产品族交互。

3. 优缺点分析

优点 缺点
保证产品族一致性:强制同一个工厂生产出来的产品都在一起配套使用,绝不会出现“混搭”Bug。 扩展“新产品”极难(违反开闭原则):如果产品族里要新增一个组件(比如加一个下拉框 Dropdown),你需要修改抽象工厂以及所有的具体工厂类。
高解耦:客户端代码与具体平台、具体产品的实现完全隔离。 代码结构复杂:抽象层级非常深,类的数量会成倍增加。
符合单一职责原则:将特定产品族的创建代码集中到一个地方。

4. Python 代码实现

💡 简单实例:跨平台 UI 组件库(Windows vs Mac)

我们来用代码解决上面提到的 UI 组件配套问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from abc import ABC, abstractmethod

# ================= 1. 抽象产品 (Abstract Products) =================
class Button(ABC):
@abstractmethod
def paint(self) -> str: pass

class Checkbox(ABC):
@abstractmethod
def render(self) -> str: pass


# ================= 2. 具体产品族 1:Windows 风格 =================
class WinButton(Button):
def paint(self): return "渲染 [Windows 风格按钮]"

class WinCheckbox(Checkbox):
def render(self): return "渲染 [Windows 风格复选框]"


# ================= 3. 具体产品族 2:Mac 风格 =================
class MacButton(Button):
def paint(self): return "渲染 [Mac 风格按钮]"

class MacCheckbox(Checkbox):
def render(self): return "渲染 [Mac 风格复选框]"


# ================= 4. 抽象工厂 (Abstract Factory) =================
class GUIFactory(ABC):
"""抽象工厂定义了创建整个产品族(按钮和复选框)的接口"""
@abstractmethod
def create_button(self) -> Button: pass

@abstractmethod
def create_checkbox(self) -> Checkbox: pass


# ================= 5. 具体工厂 (Concrete Factories) =================
class WinFactory(GUIFactory):
"""Windows 工厂只生产 Windows 组件"""
def create_button(self): return WinButton()
def create_checkbox(self): return WinCheckbox()

class MacFactory(GUIFactory):
"""Mac 工厂只生产 Mac 组件"""
def create_button(self): return MacButton()
def create_checkbox(self): return MacCheckbox()


# ================= 客户端代码 =================
def render_ui(factory: GUIFactory):
# 客户端只需要传入一个工厂,就能保证创建出来的组件是完美配套的
button = factory.create_button()
checkbox = factory.create_checkbox()

print(button.paint())
print(checkbox.render())

# 测试 Windows 环境
print("--- 初始化 Windows UI ---")
render_ui(WinFactory())

# 测试 Mac 环境
print("\n--- 初始化 Mac UI ---")
render_ui(MacFactory())

🚀 复杂实例:多数据库架构适配器(MySQL vs MongoDB)

在现代后端架构中,抽象工厂常用于多数据库/多存储源的切换。
假设你的应用需要同时支持关系型数据库(MySQL)和 NoSQL 数据库(MongoDB),它们各自都有一套独立的“连接器”和“查询器”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
from abc import ABC, abstractmethod

# ================= 抽象产品 =================
class DBConnection(ABC):
@abstractmethod
def connect(self): pass

class DBCommand(ABC):
@abstractmethod
def execute_query(self, query_str: str): pass


# ================= 具体产品:MySQL 家族 =================
class MySQLConnection(DBConnection):
def connect(self): return "MySQL: 已建立数据库连接池。"

class MySQLCommand(DBCommand):
def execute_query(self, query_str):
return f"MySQL 执行 SQL: SELECT * FROM {query_str}"


# ================= 具体产品:MongoDB 家族 =================
class MongoDBConnection(DBConnection):
def connect(self): return "MongoDB: 已连接到集群副本集。"

class MongoDBCommand(DBCommand):
def execute_query(self, query_str):
return f"MongoDB 执行 BSON 查询: db.collection.find({{ {query_str} }})"


# ================= 抽象工厂 =================
class DatabaseFactory(ABC):
@abstractmethod
def get_connection(self) -> DBConnection: pass

@abstractmethod
def get_command(self) -> DBCommand: pass


# ================= 具体工厂 =================
class RelationalDBFactory(DatabaseFactory):
def get_connection(self): return MySQLConnection()
def get_command(self): return MySQLCommand()

class NoSQLDBFactory(DatabaseFactory):
def get_connection(self): return MongoDBConnection()
def get_command(self): return MongoDBCommand()


# ================= 业务层调用 (根据配置动态加载) =================
class Application:
def __init__(self, factory: DatabaseFactory):
self.factory = factory
self.connection = self.factory.get_connection()
self.command = self.factory.get_command()

def run_business_logic(self, target: str):
print(self.connection.connect())
print(self.command.execute_query(target))


if __name__ == "__main__":
# 模拟从配置文件读取当前环境应该用哪种数据库
current_env = "nosql"

if current_env == "relational":
factory = RelationalDBFactory()
else:
factory = NoSQLDBFactory()

# 整个应用的核心业务代码完全不需要修改,直接换掉工厂即可
app = Application(factory)
app.run_business_logic("users")

区分总结:三大工厂到底有什么区别?

  • 简单工厂(不是设计模式):一个工厂类负责根据参数创建所有产品。新增产品时要改动工厂内的 if-else。
  • 工厂方法模式:一个工厂只对应一种产品(卡车工厂造卡车,轮船工厂造轮船)。
  • 抽象工厂模式:一个工厂负责生产一整套关联的产品族(Windows工厂既造Win按钮,又造Win复选框)。