工厂模式(Factory Pattern)完整详解
工厂模式是软件开发中最常用的创建型设计模式 ,核心思想是将「对象的创建」与「对象的使用」完全解耦 。
客户端无需关心对象如何实例化、依赖如何组装,只需要通过「工厂」获取目标对象,极大降低代码耦合,同时满足开闭原则、单一职责原则等设计规范。
工厂模式主要分为3 种形态,复杂度从低到高依次为:
- 简单工厂模式(静态工厂模式)
- 工厂方法模式
- 抽象工厂模式
其中工厂方法、抽象工厂属于GOF 23种经典设计模式,简单工厂是其基础简化版,工程中也极为常用。
一、简单工厂模式(Simple Factory)
1. 核心定义
又称静态工厂模式 ,由一个统一的工厂类 ,根据传入的参数/类型,动态创建不同的具体产品对象,客户端不直接new对象。
注意:简单工厂不属于GOF 23种设计模式,但它是理解工厂模式的基础。
2. 核心角色
| 角色 | 作用 |
|---|---|
| 抽象产品(Product) | 定义所有产品的公共接口/父类 |
| 具体产品(ConcreteProduct) | 实现抽象产品,是工厂创建的目标对象 |
| 工厂类(Factory) | 核心类,根据参数判断并创建具体产品 |
| 客户端(Client) | 调用工厂获取产品,不直接创建产品 |
3. 代码示例(Python)
以「生产不同形状」为例:
python
# 1. 抽象产品:形状接口
class Shape:
def draw(self):
pass
# 2. 具体产品:圆形、矩形
class Circle(Shape):
def draw(self):
print("绘制圆形")
class Rectangle(Shape):
def draw(self):
print("绘制矩形")
# 3. 简单工厂类
class ShapeFactory:
@staticmethod
def create_shape(shape_type):
if shape_type == "circle":
return Circle()
elif shape_type == "rectangle":
return Rectangle()
else:
raise ValueError("不支持的形状类型")
# 4. 客户端使用
if __name__ == "__main__":
# 客户端只调用工厂,不new具体类
shape1 = ShapeFactory.create_shape("circle")
shape1.draw()
shape2 = ShapeFactory.create_shape("rectangle")
shape2.draw()
4. 优点
- 实现创建与使用分离,客户端无需关注对象创建细节
- 代码简洁,使用成本极低
- 统一管理对象创建,便于维护
5. 缺点
- 违反开闭原则:新增产品必须修改工厂类的判断逻辑
- 工厂类职责过重,所有产品创建逻辑耦合在一起
- 产品种类过多时,工厂类代码会极度臃肿
6. 适用场景
- 产品种类少且稳定,几乎不需要扩展
- 简单业务场景,追求快速实现
二、工厂方法模式(Factory Method)
1. 核心定义
对简单工厂的升级:定义抽象工厂接口,每个具体产品对应一个专属工厂子类 ,对象实例化推迟到子类实现。
遵循开闭原则:新增产品时,只需新增产品类+对应工厂类,无需修改原有代码。
2. 核心角色
| 角色 | 作用 |
|---|---|
| 抽象产品(Product) | 产品公共接口 |
| 具体产品(ConcreteProduct) | 实现抽象产品 |
| 抽象工厂(Factory) | 定义创建产品的接口方法 |
| 具体工厂(ConcreteFactory) | 实现抽象工厂,只创建一种具体产品 |
| 客户端(Client) | 依赖抽象工厂,调用方法获取产品 |
3. 代码示例(Python)
python
# 1. 抽象产品
class Shape:
def draw(self):
pass
# 2. 具体产品
class Circle(Shape):
def draw(self):
print("绘制圆形")
class Rectangle(Shape):
def draw(self):
print("绘制矩形")
# 3. 抽象工厂
class ShapeFactory:
def create_shape(self):
pass
# 4. 具体工厂:每个产品对应一个工厂
class CircleFactory(ShapeFactory):
def create_shape(self):
return Circle()
class RectangleFactory(ShapeFactory):
def create_shape(self):
return Rectangle()
# 5. 客户端使用
if __name__ == "__main__":
# 用圆形工厂创建圆形
circle_factory = CircleFactory()
circle = circle_factory.create_shape()
circle.draw()
# 用矩形工厂创建矩形
rect_factory = RectangleFactory()
rect = rect_factory.create_shape()
rect.draw()
4. 优点
- 严格遵循开闭原则:新增产品只需新增类,不修改旧代码
- 单一职责原则:每个工厂只负责创建一种产品,逻辑清晰
- 客户端依赖抽象,不依赖具体类,耦合度极低
5. 缺点
- 类数量爆炸式增长:每加一个产品,就要加一个工厂类
- 实现复杂度高于简单工厂
6. 适用场景
- 产品种类多,且需要频繁扩展
- 希望代码严格遵循设计原则,便于长期维护
- 典型应用:JDBC 数据库连接、日志框架不同实现切换
三、抽象工厂模式(Abstract Factory)
1. 核心定义
工厂方法的进阶,用于创建一系列相关/相互依赖的产品(产品族) ,而非单个产品。
一个工厂可以生产多个关联产品,保证产品之间的兼容性。
产品族:同一品牌下的多款产品(如美的工厂生产空调+冰箱;格力工厂生产空调+冰箱)
产品等级:同一品类的不同品牌(如美的空调、格力空调)
2. 核心角色
| 角色 | 作用 |
|---|---|
| 抽象产品族 | 定义多个产品的接口(如空调、冰箱) |
| 具体产品族 | 实现抽象产品族,属于同一品牌 |
| 抽象工厂 | 定义创建整个产品族的接口 |
| 具体工厂 | 实现抽象工厂,生产一整套关联产品 |
| 客户端 | 依赖抽象工厂,获取整套产品 |
3. 代码示例(Python)
以「家电工厂(生产空调+冰箱)」为例:
python
# 1. 抽象产品族:空调、冰箱
class AirConditioner:
def cool(self):
pass
class Refrigerator:
def freeze(self):
pass
# 2. 具体产品族:美的系列、格力系列
class MediaAirConditioner(AirConditioner):
def cool(self):
print("美的空调制冷")
class MediaRefrigerator(Refrigerator):
def freeze(self):
print("美的冰箱冷冻")
class GreeAirConditioner(AirConditioner):
def cool(self):
print("格力空调制冷")
class GreeRefrigerator(Refrigerator):
def freeze(self):
print("格力冰箱冷冻")
# 3. 抽象工厂:生产整套家电
class ApplianceFactory:
def create_air_conditioner(self):
pass
def create_refrigerator(self):
pass
# 4. 具体工厂
class MediaFactory(ApplianceFactory):
def create_air_conditioner(self):
return MediaAirConditioner()
def create_refrigerator(self):
return MediaRefrigerator()
class GreeFactory(ApplianceFactory):
def create_air_conditioner(self):
return GreeAirConditioner()
def create_refrigerator(self):
return GreeRefrigerator()
# 5. 客户端使用
if __name__ == "__main__":
# 美的工厂生产整套美的家电
media_factory = MediaFactory()
media_ac = media_factory.create_air_conditioner()
media_fridge = media_factory.create_refrigerator()
media_ac.cool()
media_fridge.freeze()
# 格力工厂生产整套格力家电
gree_factory = GreeFactory()
gree_ac = gree_factory.create_air_conditioner()
gree_fridge = gree_factory.create_refrigerator()
gree_ac.cool()
gree_fridge.freeze()
4. 优点
- 强制约束产品族兼容性,避免不匹配的产品组合
- 遵循开闭原则,切换产品族只需更换工厂
- 统一管理关联产品,代码结构清晰
5. 缺点
- 扩展产品等级极难:新增一个产品(如洗衣机),所有工厂都要修改
- 复杂度最高,设计成本高
6. 适用场景
- 系统中有多个产品族,且产品族内产品相互关联
- 需要保证产品配套使用,避免混用
- 典型应用:UI组件库(不同主题的按钮+输入框+弹窗)、数据库不同方言适配
四、三种工厂模式核心对比
| 对比维度 | 简单工厂 | 工厂方法 | 抽象工厂 |
|---|---|---|---|
| 设计原则 | 违反开闭原则 | 遵循开闭原则 | 遵循开闭原则 |
| 工厂职责 | 一个工厂造所有产品 | 一个工厂造一种产品 | 一个工厂造一族产品 |
| 类数量 | 最少 | 较多 | 最多 |
| 复杂度 | 低 | 中 | 高 |
| 扩展难度 | 难(改工厂) | 易(加类) | 产品族易扩展,产品等级难扩展 |
| 核心定位 | 快速实现 | 单产品灵活扩展 | 多关联产品族管理 |
五、工厂模式的核心价值
- 解耦创建与使用:客户端只负责用对象,不负责造对象
- 统一创建逻辑 :避免代码中大量
new语句,便于统一修改 - 满足设计原则:降低耦合,提高代码可维护性、可扩展性
- 隐藏实现细节:复杂对象的依赖注入、初始化逻辑对客户端透明
六、实际工程应用
- Spring 框架 :
BeanFactory、ApplicationContext底层大量使用工厂模式创建Bean - JDBC :
DriverManager获取Connection,不同数据库驱动对应不同实现 - 日志框架:SLF4J 通过工厂适配 Logback、Log4j 等不同日志实现
- UI框架:不同主题/平台的组件创建(如移动端、PC端组件)
作为图像算法工程师(CV/医疗AI/工业视觉) ,工厂模式是工程化落地、多模型管理、实验迭代、跨平台部署 里最常用、最实用的设计模式,没有之一。
结合日常做的目标检测(YOLOv8)、分割、医疗影像算法、模型部署(ONNX/TensorRT)、实验对比 场景,直接讲:什么时候用 + 怎么写代码 + 工程收益。
一、图像处理中,什么时候必用工厂模式?
只要出现下面任意一种情况,用工厂模式直接让代码清爽10倍:
- 同时维护多个模型
YOLOv5/YOLOv8/RT-DETR/自定义检测模型、U-Net/DeepLab分割模型,快速切换对比效果。 - 同一任务有多种实现
不同NMS(普通NMS/DIoU NMS/Soft NMS)、不同预处理(医疗影像归一化/自然图像归一化)、不同后处理。 - 跨平台/跨推理引擎部署
同一套业务逻辑,切换 ONNX Runtime / TensorRT / OpenVINO / RKNN 推理。 - 实验迭代频繁
新加一个算法/模型,不改业务代码,只加新类。 - 模块化SDK封装
给前端/业务层调用,隐藏模型加载、推理、预处理细节。 - 医疗AI/工业视觉多任务
舌诊检测、尿液分析、缺陷检测等多任务统一调度。
二、结合CV实战:三种工厂怎么用?
下面全是你日常写推理代码的真实场景,Python实现,可直接放进项目。
场景1:简单工厂 → 快速切换多个检测模型(最常用)
适用 :你有YOLOv8、RT-DETR、自定义模型,想一行代码切换,不用到处改new Model()。
核心思路
一个工厂类,根据模型名称,返回对应的模型推理实例。
python
import cv2
import numpy as np
# ------------------------------
# 1. 抽象产品:模型推理基类
# ------------------------------
class Detector:
def infer(self, img: np.ndarray) -> list:
"""模型推理接口"""
raise NotImplementedError
# ------------------------------
# 2. 具体产品:不同检测模型
# ------------------------------
class YOLOv8Detector(Detector):
def __init__(self):
# 加载YOLOv8 onnx/trt模型
print("加载 YOLOv8 检测模型")
def infer(self, img):
print("YOLOv8 推理完成")
return [{"box": [10,20,100,200], "score":0.95}]
class RTDETRDetector(Detector):
def __init__(self):
print("加载 RT-DETR 检测模型")
def infer(self, img):
print("RT-DETR 推理完成")
return [{"box": [15,25,95,195], "score":0.98}]
# ------------------------------
# 3. 简单工厂:统一创建模型
# ------------------------------
class DetectorFactory:
@staticmethod
def create_detector(model_type: str = "yolov8") -> Detector:
if model_type == "yolov8":
return YOLOv8Detector()
elif model_type == "rtdetr":
return RTDETRDetector()
else:
raise ValueError("不支持的模型类型")
# ------------------------------
# 业务使用(前端/主函数)
# ------------------------------
if __name__ == "__main__":
# 想换模型只改这里,业务代码完全不动
detector = DetectorFactory.create_detector("yolov8")
img = cv2.imread("test.jpg")
result = detector.infer(img)
print(result)
你的收益
- 换模型只改一个字符串,不用改推理、后处理、绘图逻辑。
- 模型加载细节全藏在工厂里,业务层干净。
场景2:工厂方法 → 扩展新后处理算法(符合开闭原则)
适用 :你要加新的NMS、新的后处理方式,不修改原有代码,直接新增类+工厂。
比如:普通NMS、DIoU-NMS、医疗影像专用后处理。
python
# ------------------------------
# 1. 后处理接口
# ------------------------------
class PostProcess:
def process(self, preds):
raise NotImplementedError
# ------------------------------
# 2. 具体后处理
# ------------------------------
class NMSPostProcess(PostProcess):
def process(self, preds):
print("执行普通NMS")
return preds
class DIoUNMSPostProcess(PostProcess):
def process(self, preds):
print("执行DIoU-NMS")
return preds
# ------------------------------
# 3. 工厂方法:一个处理对应一个工厂
# ------------------------------
class PostProcessFactory:
def create(self) -> PostProcess:
raise NotImplementedError
class NMSFactory(PostProcessFactory):
def create(self):
return NMSPostProcess()
class DIoUFactory(PostProcessFactory):
def create(self):
return DIoUNMSPostProcess()
# ------------------------------
# 使用
# ------------------------------
factory = DIoUFactory()
post = factory.create()
post.process([])
你的收益
- 以后加Soft NMS、后处理滤波,只新增类,不碰旧代码。
- 多人协作不会改乱核心逻辑。
场景3:抽象工厂 → 整套CV流水线(预处理+模型+后处理)
最贴合你医疗AI/尿液检测/舌诊项目
一个工厂生产一整套流程 :
预处理 → 模型推理 → 后处理
不同任务(检测/分割)、不同硬件(TensorRT/ONNX)用不同工厂。
python
# ------------------------------
# 产品族:预处理、推理、后处理
# ------------------------------
class PreProcess:
def run(self, img): pass
class Infer:
def run(self, img): pass
class PostProcess:
def run(self, pred): pass
# ------------------------------
# YOLOv8 + TensorRT 整套流水线
# ------------------------------
class TRTYoloPreProcess(PreProcess):
def run(self, img): print("TRT-YOLO 预处理:letterbox+归一化")
class TRTYoloInfer(Infer):
def run(self, img): print("TensorRT 推理")
class TRTYoloPostProcess(PostProcess):
def run(self, pred): print("TRT-YOLO NMS后处理")
# ------------------------------
# 抽象工厂
# ------------------------------
class CVFactory:
def create_pre(self) -> PreProcess: pass
def create_infer(self) -> Infer: pass
def create_post(self) -> PostProcess: pass
# ------------------------------
# 具体工厂:YOLOv8-TensorRT 工厂
# ------------------------------
class TRTYoloFactory(CVFactory):
def create_pre(self): return TRTYoloPreProcess()
def create_infer(self): return TRTYoloInfer()
def create_post(self): return TRTYoloPostProcess()
# ------------------------------
# 业务调用:一套流程直接跑
# ------------------------------
factory = TRTYoloFactory()
pre = factory.create_pre()
infer = factory.create_infer()
post = factory.create_post()
img = None
pre.run(img)
feat = infer.run(img)
post.run(feat)
你的收益
- 切换部署平台(TensorRT ↔ ONNX ↔ RKNN),只换工厂。
- 检测、分割、医疗影像任务,流水线高度统一。
- 项目工程化极强,适合做成SDK给别人调用。
三、作为图像算法工程师,工厂模式的核心价值
- 实验效率爆炸
对比YOLOv8/RT-DETR/自定义模型,不用删改代码,直接传参切换。 - 工程落地不混乱
模型加载、推理、预处理解耦,不会出现几千行的infer.py。 - 跨硬件部署零成本
TensorRT/ONNX/RKNN 一套代码适配,业务层完全无感。 - 多人协作不冲突
算法同学加模型,工程同学改流程,互不干扰。 - 医疗/工业视觉项目必备
多任务、多模型、多设备,必须用工厂做模块化管理。
四、一句话总结(CV视角)
- 简单工厂:日常快速切换模型,用得最多。
- 工厂方法:扩展新算法/后处理,保证代码可维护。
- 抽象工厂:封装整套CV流水线,做工程化SDK。