工厂模式(Factory Pattern)完整详解
工厂模式是软件开发中最常用的创建型设计模式,核心思想是将「对象的创建」与「对象的使用」完全解耦。
客户端无需关心对象如何实例化、依赖如何组装,只需要通过「工厂」获取目标对象,极大降低代码耦合,同时满足开闭原则、单一职责原则等设计规范。
工厂模式主要分为3 种形态,复杂度从低到高依次为:
- 简单工厂模式(静态工厂模式)
- 工厂方法模式
- 抽象工厂模式
其中工厂方法、抽象工厂属于GOF 23种经典设计模式,简单工厂是其基础简化版,工程中也极为常用。
一、简单工厂模式(Simple Factory)
1. 核心定义
又称静态工厂模式,由一个统一的工厂类,根据传入的参数/类型,动态创建不同的具体产品对象,客户端不直接new对象。
注意:简单工厂不属于GOF 23种设计模式,但它是理解工厂模式的基础。
2. 核心角色
| 角色 | 作用 |
|---|---|
| 抽象产品(Product) | 定义所有产品的公共接口/父类 |
| 具体产品(ConcreteProduct) | 实现抽象产品,是工厂创建的目标对象 |
| 工厂类(Factory) | 核心类,根据参数判断并创建具体产品 |
| 客户端(Client) | 调用工厂获取产品,不直接创建产品 |
3. 代码示例(Python)
以「生产不同形状」为例:
# 1. 抽象产品:形状接口classShape:defdraw(self):pass# 2. 具体产品:圆形、矩形classCircle(Shape):defdraw(self):print("绘制圆形")classRectangle(Shape):defdraw(self):print("绘制矩形")# 3. 简单工厂类classShapeFactory:@staticmethoddefcreate_shape(shape_type):ifshape_type=="circle":returnCircle()elifshape_type=="rectangle":returnRectangle()else:raiseValueError("不支持的形状类型")# 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)
# 1. 抽象产品classShape:defdraw(self):pass# 2. 具体产品classCircle(Shape):defdraw(self):print("绘制圆形")classRectangle(Shape):defdraw(self):print("绘制矩形")# 3. 抽象工厂classShapeFactory:defcreate_shape(self):pass# 4. 具体工厂:每个产品对应一个工厂classCircleFactory(ShapeFactory):defcreate_shape(self):returnCircle()classRectangleFactory(ShapeFactory):defcreate_shape(self):returnRectangle()# 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)
以「家电工厂(生产空调+冰箱)」为例:
# 1. 抽象产品族:空调、冰箱classAirConditioner:defcool(self):passclassRefrigerator:deffreeze(self):pass# 2. 具体产品族:美的系列、格力系列classMediaAirConditioner(AirConditioner):defcool(self):print("美的空调制冷")classMediaRefrigerator(Refrigerator):deffreeze(self):print("美的冰箱冷冻")classGreeAirConditioner(AirConditioner):defcool(self):print("格力空调制冷")classGreeRefrigerator(Refrigerator):deffreeze(self):print("格力冰箱冷冻")# 3. 抽象工厂:生产整套家电classApplianceFactory:defcreate_air_conditioner(self):passdefcreate_refrigerator(self):pass# 4. 具体工厂classMediaFactory(ApplianceFactory):defcreate_air_conditioner(self):returnMediaAirConditioner()defcreate_refrigerator(self):returnMediaRefrigerator()classGreeFactory(ApplianceFactory):defcreate_air_conditioner(self):returnGreeAirConditioner()defcreate_refrigerator(self):returnGreeRefrigerator()# 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()。
核心思路
一个工厂类,根据模型名称,返回对应的模型推理实例。
importcv2importnumpyasnp# ------------------------------# 1. 抽象产品:模型推理基类# ------------------------------classDetector:definfer(self,img:np.ndarray)->list:"""模型推理接口"""raiseNotImplementedError# ------------------------------# 2. 具体产品:不同检测模型# ------------------------------classYOLOv8Detector(Detector):def__init__(self):# 加载YOLOv8 onnx/trt模型print("加载 YOLOv8 检测模型")definfer(self,img):print("YOLOv8 推理完成")return[{"box":[10,20,100,200],"score":0.95}]classRTDETRDetector(Detector):def__init__(self):print("加载 RT-DETR 检测模型")definfer(self,img):print("RT-DETR 推理完成")return[{"box":[15,25,95,195],"score":0.98}]# ------------------------------# 3. 简单工厂:统一创建模型# ------------------------------classDetectorFactory:@staticmethoddefcreate_detector(model_type:str="yolov8")->Detector:ifmodel_type=="yolov8":returnYOLOv8Detector()elifmodel_type=="rtdetr":returnRTDETRDetector()else:raiseValueError("不支持的模型类型")# ------------------------------# 业务使用(前端/主函数)# ------------------------------if__name__=="__main__":# 想换模型只改这里,业务代码完全不动detector=DetectorFactory.create_detector("yolov8")img=cv2.imread("test.jpg")result=detector.infer(img)print(result)你的收益
- 换模型只改一个字符串,不用改推理、后处理、绘图逻辑。
- 模型加载细节全藏在工厂里,业务层干净。
场景2:工厂方法 → 扩展新后处理算法(符合开闭原则)
适用:你要加新的NMS、新的后处理方式,不修改原有代码,直接新增类+工厂。
比如:普通NMS、DIoU-NMS、医疗影像专用后处理。
# ------------------------------# 1. 后处理接口# ------------------------------classPostProcess:defprocess(self,preds):raiseNotImplementedError# ------------------------------# 2. 具体后处理# ------------------------------classNMSPostProcess(PostProcess):defprocess(self,preds):print("执行普通NMS")returnpredsclassDIoUNMSPostProcess(PostProcess):defprocess(self,preds):print("执行DIoU-NMS")returnpreds# ------------------------------# 3. 工厂方法:一个处理对应一个工厂# ------------------------------classPostProcessFactory:defcreate(self)->PostProcess:raiseNotImplementedErrorclassNMSFactory(PostProcessFactory):defcreate(self):returnNMSPostProcess()classDIoUFactory(PostProcessFactory):defcreate(self):returnDIoUNMSPostProcess()# ------------------------------# 使用# ------------------------------factory=DIoUFactory()post=factory.create()post.process([])你的收益
- 以后加Soft NMS、后处理滤波,只新增类,不碰旧代码。
- 多人协作不会改乱核心逻辑。
场景3:抽象工厂 → 整套CV流水线(预处理+模型+后处理)
最贴合你医疗AI/尿液检测/舌诊项目
一个工厂生产一整套流程:预处理 → 模型推理 → 后处理
不同任务(检测/分割)、不同硬件(TensorRT/ONNX)用不同工厂。
# ------------------------------# 产品族:预处理、推理、后处理# ------------------------------classPreProcess:defrun(self,img):passclassInfer:defrun(self,img):passclassPostProcess:defrun(self,pred):pass# ------------------------------# YOLOv8 + TensorRT 整套流水线# ------------------------------classTRTYoloPreProcess(PreProcess):defrun(self,img):print("TRT-YOLO 预处理:letterbox+归一化")classTRTYoloInfer(Infer):defrun(self,img):print("TensorRT 推理")classTRTYoloPostProcess(PostProcess):defrun(self,pred):print("TRT-YOLO NMS后处理")# ------------------------------# 抽象工厂# ------------------------------classCVFactory:defcreate_pre(self)->PreProcess:passdefcreate_infer(self)->Infer:passdefcreate_post(self)->PostProcess:pass# ------------------------------# 具体工厂:YOLOv8-TensorRT 工厂# ------------------------------classTRTYoloFactory(CVFactory):defcreate_pre(self):returnTRTYoloPreProcess()defcreate_infer(self):returnTRTYoloInfer()defcreate_post(self):returnTRTYoloPostProcess()# ------------------------------# 业务调用:一套流程直接跑# ------------------------------factory=TRTYoloFactory()pre=factory.create_pre()infer=factory.create_infer()post=factory.create_post()img=Nonepre.run(img)feat=infer.run(img)post.run(feat)你的收益
- 切换部署平台(TensorRT ↔ ONNX ↔ RKNN),只换工厂。
- 检测、分割、医疗影像任务,流水线高度统一。
- 项目工程化极强,适合做成SDK给别人调用。
三、作为图像算法工程师,工厂模式的核心价值
- 实验效率爆炸
对比YOLOv8/RT-DETR/自定义模型,不用删改代码,直接传参切换。 - 工程落地不混乱
模型加载、推理、预处理解耦,不会出现几千行的infer.py。 - 跨硬件部署零成本
TensorRT/ONNX/RKNN 一套代码适配,业务层完全无感。 - 多人协作不冲突
算法同学加模型,工程同学改流程,互不干扰。 - 医疗/工业视觉项目必备
多任务、多模型、多设备,必须用工厂做模块化管理。
四、一句话总结(CV视角)
- 简单工厂:日常快速切换模型,用得最多。
- 工厂方法:扩展新算法/后处理,保证代码可维护。
- 抽象工厂:封装整套CV流水线,做工程化SDK。