news 2026/6/10 1:20:10

PHP工厂模式 = 抽象工厂 = 简单工厂?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHP工厂模式 = 抽象工厂 = 简单工厂?

PHP 中的“工厂模式” ≠ “抽象工厂” ≠ “简单工厂”
三者虽同属创建型设计模式,但抽象层级、适用场景、解决的问题截然不同。混淆它们,会导致过度设计抽象不足


一、核心意图:解决什么问题?

模式核心意图问题场景
简单工厂(Simple Factory)封装对象创建逻辑客户端不想直接new,但产品类型固定
工厂方法(Factory Method)将对象创建延迟到子类产品族单一,但创建逻辑需子类定制
抽象工厂(Abstract Factory)创建一系列相关/依赖对象产品族多维,需保证组合一致性

🔑关键区分

  • 简单工厂:1 个工厂,N 个产品;
  • 工厂方法:N 个工厂(子类),1 个产品线;
  • 抽象工厂:1 个工厂,N×M 个产品族。

二、结构对比:UML 精简版

1.简单工厂
+----------------+ | SimpleFactory | +----------------+ | + create(type) | +----------------+ | v +--------+--------+ | ProductA | ProductB | +------------------+
  • 特点
    • 无继承,工厂是普通类;
    • 违反开闭原则(新增产品需改工厂)。
2.工厂方法
+----------------+ +---------------------+ | Creator |<------| ConcreteCreatorA | +----------------+ +---------------------+ | + factoryMethod()| | + factoryMethod() | +----------------+ +---------------------+ | | v v +----------------+ +---------------------+ | Product |<------| ConcreteProductA | +----------------+ +---------------------+
  • 特点
    • Creator 定义接口,子类实现
    • 符合开闭原则(新增产品只需加子类)。
3.抽象工厂
+------------------+ +-----------------------+ | AbstractFactory |<------| ConcreteFactoryA | +------------------+ +-----------------------+ | + createProductA()| | + createProductA() | | + createProductB()| | + createProductB() | +------------------+ +-----------------------+ | | v v +------------------+ +-----------------------+ | AbstractProductA |<------| ConcreteProductA1 | | AbstractProductB |<------| ConcreteProductB1 | +------------------+ +-----------------------+
  • 特点
    • 工厂创建多个产品族
    • 保证产品组合一致性(如 Win 按钮 + Win 文本框)。

三、PHP 实现:代码即文档

1.简单工厂(适合产品稳定)
// 产品接口interfaceLogger{publicfunctionlog(string$message);}// 具体产品classFileLoggerimplementsLogger{publicfunctionlog(string$message){/* 写文件 */}}classDbLoggerimplementsLogger{publicfunctionlog(string$message){/* 写 DB */}}// 简单工厂classLoggerFactory{publicstaticfunctioncreate(string$type):Logger{returnmatch($type){'file'=>newFileLogger(),'db'=>newDbLogger(),default=>thrownewException('Invalid logger type'),};}}// 使用$logger=LoggerFactory::create('file');
  • 优点:简单直接;
  • 缺点:新增RedisLogger需改工厂。
2.工厂方法(适合创建逻辑多变)
// 抽象 CreatorabstractclassLoggerFactory{abstractpublicfunctioncreateLogger():Logger;publicfunctionlog(string$message){$this->createLogger()->log($message);}}// 具体 CreatorclassFileLoggerFactoryextendsLoggerFactory{publicfunctioncreateLogger():Logger{returnnewFileLogger();}}classDbLoggerFactoryextendsLoggerFactory{publicfunctioncreateLogger():Logger{returnnewDbLogger();}}// 使用$factory=newFileLoggerFactory();$factory->log('Hello');
  • 优点:符合开闭原则;
  • 缺点:类爆炸(每产品需 1 Creator + 1 Product)。
3.抽象工厂(适合产品族组合)
// 抽象产品族interfaceButton{publicfunctionrender();}interfaceCheckbox{publicfunctionrender();}// 具体产品族classWinButtonimplementsButton{publicfunctionrender(){echo"Win Button";}}classWinCheckboximplementsCheckbox{publicfunctionrender(){echo"Win Checkbox";}}classMacButtonimplementsButton{publicfunctionrender(){echo"Mac Button";}}classMacCheckboximplementsCheckbox{publicfunctionrender(){echo"Mac Checkbox";}}// 抽象工厂interfaceGUIFactory{publicfunctioncreateButton():Button;publicfunctioncreateCheckbox():Checkbox;}// 具体工厂classWinFactoryimplementsGUIFactory{publicfunctioncreateButton():Button{returnnewWinButton();}publicfunctioncreateCheckbox():Checkbox{returnnewWinCheckbox();}}classMacFactoryimplementsGUIFactory{publicfunctioncreateButton():Button{returnnewMacButton();}publicfunctioncreateCheckbox():Checkbox{returnnewMacCheckbox();}}// 使用$factory=newWinFactory();$button=$factory->createButton();$checkbox=$factory->createCheckbox();
  • 优点:保证产品族一致性;
  • 缺点:扩展产品族需改所有工厂。

四、适用场景:PHP 项目中的选择指南

场景推荐模式原因
日志驱动(File/DB/Redis)简单工厂产品类型固定,无需子类扩展
多环境配置(Dev/Staging/Prod)工厂方法每环境创建逻辑不同,需子类定制
UI 主题切换(Win/Mac/iOS)抽象工厂需保证按钮+文本框+下拉框风格一致
支付网关(Alipay/WeChat/PayPal)简单工厂 or 工厂方法若仅创建支付对象 → 简单工厂;若需创建支付+通知对象 → 抽象工厂

💡Laravel 中的实践

  • 简单工厂Cache::store('redis')
  • 工厂方法EventServiceProvidershouldDiscoverEvents()
  • 抽象工厂:极少直接使用,但服务容器(Service Container) 可替代其功能。

五、高危误区

🚫 误区 1:“抽象工厂是工厂方法的升级版”
  • 真相
    • 工厂方法解决“单产品创建”
    • 抽象工厂解决“多产品组合”
    • 二者解决不同维度问题
🚫 误区 2:“必须用工厂模式替代 new”
  • 真相
    • 简单场景直接new更清晰
    • 过度抽象增加理解成本
🚫 误区 3:“Laravel 服务容器 = 抽象工厂”
  • 真相
    • 服务容器是依赖注入容器
    • 可通过绑定实现工厂逻辑,但非模式本身

六、终极心法:模式是工具,不是教条

不要问“该用哪种工厂”,
而要问“当前问题需要什么抽象”

  • 简单问题 → 简单工厂
  • 创建逻辑多变 → 工厂方法
  • 产品族组合 → 抽象工厂

真正的工程能力,
不在“知道模式”,
而在“知道何时不用模式”

这,才是 PHP 程序员的设计智慧。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 15:04:44

Wan2.2完整指南:如何在消费级显卡上实现电影级视频生成

Wan2.2完整指南&#xff1a;如何在消费级显卡上实现电影级视频生成 【免费下载链接】Wan2.2-TI2V-5B-Diffusers 项目地址: https://ai.gitcode.com/hf_mirrors/Wan-AI/Wan2.2-TI2V-5B-Diffusers 2025年7月28日&#xff0c;阿里巴巴开源了新一代视频生成模型Wan2.2&…

作者头像 李华
网站建设 2026/6/10 4:00:58

PyTorch TensorBoard可视化训练过程指标

PyTorch TensorBoard可视化训练过程指标 在深度学习项目中&#xff0c;你是否曾面对终端里滚动的损失值感到迷茫&#xff1f;哪怕模型每轮输出一个数字&#xff0c;你也很难判断它是在稳步收敛&#xff0c;还是陷入了震荡或过拟合。更别提当多个实验并行时&#xff0c;仅靠日志…

作者头像 李华
网站建设 2026/6/10 15:07:07

DBA手记:Oracle迁移卡壳3天,金仓72小时完成CDR全量替换

DBA手记&#xff1a;Oracle迁移卡壳3天&#xff0c;金仓72小时完成CDR全量替换 凌晨两点&#xff0c;机房的冷光映在脸上&#xff0c;我盯着监控面板上那条停滞不前的Oracle数据同步进度条&#xff0c;内心焦灼。第二天一早&#xff0c;全院门诊系统即将上线&#xff0c;而我们…

作者头像 李华
网站建设 2026/6/10 0:47:10

ClickHouse地理空间分析的5个高效实践技巧

ClickHouse地理空间分析的5个高效实践技巧 【免费下载链接】ClickHouse ClickHouse 是一个免费的大数据分析型数据库管理系统。 项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse 如何用ClickHouse解决海量地理数据查询的行业痛点&#xff1f;当物流轨迹数…

作者头像 李华
网站建设 2026/6/10 16:48:43

使用conda list和pip freeze检查PyTorch依赖完整性

使用 conda list 和 pip freeze 检查 PyTorch 依赖完整性 在深度学习项目开发中&#xff0c;一个看似不起眼却频频引发灾难的问题是&#xff1a;“为什么我的代码在本地能跑&#xff0c;在服务器上就报错&#xff1f;” 更具体一点&#xff1a;明明安装了 PyTorch&#xff0c;为…

作者头像 李华
网站建设 2026/6/10 14:20:41

[Linux]学习笔记系列 -- [fs]mnt_idmapping

title: mnt_idmapping categories: linuxfs tags:linuxfs abbrlink: f1c7d54a date: 2025-10-03 09:01:49 https://github.com/wdfk-prog/linux-study 文章目录fs/mnt_idmapping.c 挂载ID映射(Mount ID Mapping) 容器内安全的文件系统访问历史与背景这项技术是为了解决什么特定…

作者头像 李华