news 2026/7/25 18:03:33

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/7/22 10:54:21

Docker快速部署一个轻量级邮件发送 API 服务

1、 这是一个基于 Gin 框架的邮件发送服务&#xff0c;对外提供API&#xff0c;实质是通过第三方SMTP发送邮件• 提供一个简易的Web UI&#xff0c;可在线查看发送记录 • 支持Docker快速部署&#xff0c;非常轻量 • 通过一个GET请求就能发送邮件&#xff0c;适合快速接入终端…

作者头像 李华
网站建设 2026/7/21 21:12:26

Manim LaTeX魔法:让数学公式在动画中翩翩起舞

Manim LaTeX魔法&#xff1a;让数学公式在动画中翩翩起舞 【免费下载链接】manim A community-maintained Python framework for creating mathematical animations. 项目地址: https://gitcode.com/GitHub_Trending/man/manim 还在为数学教学视频中的公式渲染问题头疼…

作者头像 李华
网站建设 2026/7/24 14:18:28

Vue Router单元测试完全指南:从零开始构建可靠路由测试

Vue Router单元测试完全指南&#xff1a;从零开始构建可靠路由测试 【免费下载链接】vue-router &#x1f6a6; The official router for Vue 2 项目地址: https://gitcode.com/gh_mirrors/vu/vue-router Vue Router作为Vue.js 2的官方路由解决方案&#xff0c;在现代单…

作者头像 李华
网站建设 2026/7/22 19:01:20

StabilityMatrix:AI绘画环境管理的革命性解决方案

StabilityMatrix&#xff1a;AI绘画环境管理的革命性解决方案 【免费下载链接】StabilityMatrix Multi-Platform Package Manager for Stable Diffusion 项目地址: https://gitcode.com/gh_mirrors/st/StabilityMatrix 在AI绘画创作蓬勃发展的今天&#xff0c;技术门槛和…

作者头像 李华
网站建设 2026/7/24 3:24:12

3Dmol.js快速上手:打造专业的分子可视化应用

3Dmol.js快速上手&#xff1a;打造专业的分子可视化应用 【免费下载链接】3Dmol.js WebGL accelerated JavaScript molecular graphics library 项目地址: https://gitcode.com/gh_mirrors/3d/3Dmol.js 在计算生物学、药物设计和材料科学领域&#xff0c;分子结构的可视…

作者头像 李华