当前位置: 首页 > news >正文

工厂模式和抽象工厂模式的区别

1. 核心维度的区别

我们可以从两个维度来看待这个问题:

维度 工厂方法模式 (Factory Method) 抽象工厂模式 (Abstract Factory)
产品数量 单一产品 产品族 (Product Family)
接口方法 只有一个 Create() 方法 有多个方法 CreateA(), CreateB()...
关注点 只要把对象造出来就行,不需要考虑搭配 必须保证造出来的一堆对象是配套的,不能混用
维度举例 比如:只生产“枪” 比如:生产“枪” + “子弹” + “瞄准镜”
复杂度 较低 较高

2. 生动的比喻

A. 工厂方法模式 (Factory Method)

就像“单一品牌的专卖店”,但只卖一样东西

  • 需求: 你想买辆车。
  • 奔驰工厂: 只负责造 奔驰车
  • 宝马工厂: 只负责造 宝马车
  • 客户端: 你找奔驰工厂,只能拿到奔驰车,拿不到别的。

B. 抽象工厂模式 (Abstract Factory)

就像“品牌全家桶”或者“套装装备”

  • 需求: 你不仅要买车,还要配套的钥匙、配套的轮胎。
  • 奔驰工厂: 负责造 奔驰车 + 奔驰钥匙 + 奔驰轮胎
  • 宝马工厂: 负责造 宝马车 + 宝马钥匙 + 宝马轮胎
  • 客户端: 你找奔驰工厂,它会给你一整套奔驰的东西。
  • 约束: 你绝对不会从奔驰工厂里拿到“宝马的钥匙”。(这就是抽象工厂的核心价值:防止混搭)

3. 代码结构的直观对比

工厂方法 (Factory Method)

接口里只有一个函数,生产一种东西。

class ICarFactory {
public:// 只有一个 Createvirtual ICar* CreateCar() = 0; 
};// 具体工厂
class BenzFactory : public ICarFactory {ICar* CreateCar() override { return new BenzCar(); }
};

抽象工厂 (Abstract Factory)

接口里有一组函数,生产一系列相关的东西。

class ICarSuiteFactory {
public:// 有一组 Create,它们是配套的virtual ICar* CreateCar() = 0;virtual IKey* CreateKey() = 0;virtual ITire* CreateTire() = 0;
};// 具体工厂
class BenzSuiteFactory : public ICarSuiteFactory {ICar* CreateCar()  override { return new BenzCar(); }IKey* CreateKey()  override { return new BenzKey(); } // 必须是奔驰钥匙ITire* CreateTire() override { return new BenzTire(); } // 必须是奔驰轮胎
};

4. 扩展性的区别 (开闭原则 OCP 的不同侧重)

这是最让架构师头疼的地方,两者的优缺点是互补的:

A. 工厂方法模式

  • 增加新品牌(如奥迪): 非常容易。写一个 AudiCarAudiFactory 即可。符合 OCP。
  • 增加新产品(如造卡车): 需要新建一套接口。因为原来的工厂只造轿车。

B. 抽象工厂模式

  • 增加新系列(如奥迪系列): 非常容易。写一个 AudiSuiteFactory,里面造奥迪车、奥迪钥匙。符合 OCP。
  • 增加新产品(如增加“方向盘”): 非常痛苦(灾难级)
    • 你需要修改 ICarSuiteFactory 接口,增加 CreateSteeringWheel()
    • 后果: 所有的具体工厂(奔驰工厂、宝马工厂...)全部都要修改代码来实现这个新函数。这严重违反了开闭原则。

总结:如何选择?

  1. 问自己:我需要创建的对象,是“孤立”的,还是“成套”的?
    • 如果只是创建一个 Logger,或者一个 ThreadPool,用 工厂方法
    • 如果需要创建 GUI 皮肤(按钮+背景+滚动条必须风格一致),或者数据库组件(Connection+Command+Result必须全是 MySQL 的),用 抽象工厂
  2. 大多数情况下,工厂方法模式就够用了。 抽象工厂由于太重,且接口难以修改,只有在确实有“产品族约束”时才使用。
http://www.gsyq.cn/news/127776.html

相关文章:

  • 洞察:MCP与Function Calling区别
  • 快!太快了!一键生成!一键导出!微信自动统计数据报表来了!
  • 对比:字节DeerFlow与阿里DeepResearch
  • 【后端开发笔记】JVM底层原理-垃圾回收篇 - 指南
  • 电路板维修
  • 备份恢复模块 - Cordova与OpenHarmony混合开发实战
  • 第2章 变量和基本类型
  • 年前“催婚大作战”,用“技术思维”解决婚恋问题
  • 红黑树
  • 账户增删改查与余额统计 Cordova 与 OpenHarmony 混合开发实战
  • AI协作平台提供论文框架建议与内容优化,适合团队合作研究
  • Matlab/Simulink中的Buck型双向DC/DC变换器:一阶、二阶LADRC与PI控...
  • 【MongoDB实战】第10章 新手避坑指南:90%的人都会踩的错误
  • 【图数据库与知识图谱】第一部分:基石篇——图与图谱的基本认知
  • 基于三电平SVPWM改进技术的异步电机感应电机直接转矩控制性能研究参考文献参考研究及其优劣对比
  • Day35less--嵌套
  • 如何用AI工具复现数学建模优秀论文?这10款写作助手兼排版利器别错过
  • Azure RTOS ThreadX 是什么?
  • 从文献复现到期刊排版:10个AI写作工具让数学建模论文更轻松
  • 传统写作耗时?这10个AI工具实现数学建模论文复现与排版自动化
  • 手把手带你读Corespec:逻辑链路控制与适配协议(L2CAP) 上
  • 基于深度学习的螺栓螺母检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
  • 经典算法题型之俄罗斯套娃信封问题(二)
  • BetterYeah智能体开发:插件概述
  • 重练算法(代码随想录版) day46 - 动态规划part13
  • 靠谱的厦门考研公司哪个好
  • Linux系统退出 vim 三种情况 + vim 三种模式
  • 震惊!这家酶制剂公司竟让行业炸锅
  • Emacs设置自动换行
  • Type-C接口跟USB接口有什么区别?