抽象工厂模式解决的是统一创建一组有内在关联的对象,如MySQL或PostgreSQL的连接、游标、事务管理器等产品族,适用于多厂商、多组件、强契约且需运行时动态切换整套实现的场景。

抽象工厂模式在Python中不解决“连接数据库”的问题,它解决的是“如何统一创建一组有内在关联的对象”——比如 MySQL 连接 + MySQL 游标 + MySQL 事务管理器,和 PostgreSQL 连接 + PostgreSQL 游标 + PostgreSQL 事务管理器,这两套对象不能混用。
什么时候该用抽象工厂,而不是直接写 mysql.connector.connect()?
当你需要在运行时动态切换整套数据库实现(比如开发用 SQLite、测试用 PostgreSQL、生产用 MySQL),且各套实现之间存在强耦合(例如游标类型依赖连接类型、事务对象必须和连接同厂商),这时抽象工厂才真正有用。如果只是简单连个库,用 sqlalchemy.create_engine() 或原生驱动更直接。
- 抽象工厂适合多厂商、多组件、强契约的场景;单连接字符串切换不属于它的用武之地
- Python 没有接口强制约束,靠约定和文档维持“工厂产出对象必须兼容”——这点容易被忽视,导致后期类型错配
- 工厂类本身会变重:每个新数据库类型都要新增一个具体工厂类 + 一套产品类,扩展成本高于配置驱动方案
抽象工厂的核心结构:抽象工厂类 + 产品族接口 + 具体工厂实现
关键不是“怎么写”,而是“怎么避免把工厂写成一堆 if vendor == 'mysql' 的分支”。正确做法是让每个具体工厂只负责自己那一套产品创建逻辑:
from abc import ABC, abstractmethod
class DBConnection(ABC):
@abstractmethod
def connect(self): pass
class DBCursor(ABC):
@abstractmethod
def execute(self, sql): pass
class DBFactory(ABC):
@abstractmethod
def create_connection(self) -> DBConnection: ...
@abstractmethod
def create_cursor(self) -> DBCursor: ...
class MySQLFactory(DBFactory):
def create_connection(self): return MySQLConnection()
def create_cursor(self): return MySQLCursor()
class PostgreSQLFactory(DBFactory):
def create_connection(self): return PostgreSQLConnection()
def create_cursor(self): return PostgreSQLCursor()
注意:这里 MySQLConnection 和 PostgreSQLConnection 必须都实现 connect(),但内部调用的是各自驱动(mysql.connector.connect 或 psycopg2.connect)——抽象工厂不封装驱动细节,只封装“谁和谁配对”。
立即学习“Python免费学习笔记(深入)”;
实际使用时最容易踩的坑:类型丢失与运行时错配
Python 的鸭子类型会让看似正确的代码在运行时报错,比如把 MySQLCursor 传给期望 PostgreSQLConnection 的事务管理器——因为两者没有共同基类约束,IDE 和类型检查器(如 mypy)也难发现。
- 务必为每类产品定义明确的抽象基类(
DBConnection、DBCursor),并在具体类中显式继承,否则工厂失去契约意义 - 不要在工厂方法里做参数校验(如判断 host 是否合法),那是连接类自己的职责;工厂只管“创建”,不负责“验证”
- 避免让工厂返回
dict或tuple——这等于放弃类型提示和 IDE 自动补全,抽象就白做了 - 如果项目已用
SQLAlchemy,强行套抽象工厂反而增加维护负担;它的create_engine本身就是一种轻量级工厂
抽象工厂真正的复杂点不在代码结构,而在于识别出哪些对象确实构成“不可拆分的产品族”。多数 Python 项目其实只需要一个可配置的连接工厂函数,而非一整套抽象类体系。


















