概述
工厂模式(Factory Method Pattern)又称“工厂方法”,是创建型设计模式的核心成员,也是对简单工厂模式的优化升级。其核心目标是将对象创建逻辑延迟到子类,通过定义一个创建对象的抽象接口(工厂接口/抽象工厂类),由子类决定具体实例化哪一个产品类,实现“开放-封闭原则”,解决简单工厂模式中新增产品需修改工厂类的问题。
核心价值
-
遵循开闭原则:新增产品时无需修改原有工厂逻辑,仅需新增对应产品类和工厂子类,扩展性更强;
-
解耦更彻底:抽象工厂与抽象产品对应,客户端仅依赖抽象层,不依赖具体实现,降低代码耦合度;
-
职责单一化:每个工厂子类仅负责创建一种产品,工厂逻辑清晰,便于维护和迭代;
-
灵活性提升:支持动态切换产品实现,客户端可通过替换工厂子类,切换不同的产品实例。
适用场景
-
产品类数量较多且可能持续扩展(如超过5个同类产品),需避免修改原有工厂逻辑;
-
客户端不关心产品创建细节,仅需通过工厂获取产品,且需支持产品动态切换;
-
产品类具有共同的父类或实现统一接口,工厂类也遵循统一的抽象接口。
注意事项
-
类数量增加:每新增一个产品,需同时新增对应的工厂子类,可能导致类数量膨胀(trade-off 为扩展性);
-
避免过度设计:若产品变动极少,简单工厂模式更简洁,无需引入抽象工厂和多个子类;
-
依赖抽象:客户端必须依赖抽象工厂和抽象产品,而非具体实现,否则失去解耦意义。
完整代码
<?php
declare(strict_types = 1);
/**
* 产品接口:定义所有产品的统一规范
* Interface ProductInterface
*/
interface ProductInterface
{
public function doService(): string;
}
/**
* 具体产品A:支付宝支付(实现产品接口)
* Class AlipayProduct
*/
class AlipayProduct implements ProductInterface
{
public function doService(): string
{
return "支付宝支付:执行订单扣款、回调通知逻辑";
}
}
/**
* 具体产品B:微信支付(实现产品接口)
* Class WechatPayProduct
*/
class WechatPayProduct implements ProductInterface
{
public function doService(): string
{
return "微信支付:执行订单预支付、支付结果校验逻辑";
}
}
/**
* 抽象工厂接口:定义工厂的统一规范(创建产品的接口)
* Interface FactoryInterface
*/
interface FactoryInterface
{
public function createProduct(): ProductInterface;
}
/**
* 具体工厂A:支付宝工厂(负责创建支付宝产品实例)
* Class AlipayFactory
*/
class AlipayFactory implements FactoryInterface
{
public function createProduct(): ProductInterface
{
// 可添加产品初始化逻辑(如加载支付宝配置、初始化客户端)
$this->initAlipayConfig();
return new AlipayProduct();
}
// 支付宝专属初始化逻辑
private function initAlipayConfig(): void
{
// 模拟加载配置:如APP_ID、私钥、公钥等
// $config = require_once 'alipay_config.php';
}
}
/**
* 具体工厂B:微信支付工厂(负责创建微信支付产品实例)
* Class WechatPayFactory
*/
class WechatPayFactory implements FactoryInterface
{
public function createProduct(): ProductInterface
{
// 微信支付专属初始化逻辑(如加载证书、初始化SDK)
$this->initWechatPayConfig();
return new WechatPayProduct();
}
// 微信支付专属初始化逻辑
private function initWechatPayConfig(): void
{
// 模拟加载配置:如APP_ID、商户号、API密钥等
// $config = require_once 'wechatpay_config.php';
}
}
// 测试代码
try {
// 1. 使用支付宝工厂创建支付宝产品
$alipayFactory = new AlipayFactory();
$alipay = $alipayFactory->createProduct();
echo $alipay->doService() . PHP_EOL; // 输出:支付宝支付:执行订单扣款、回调通知逻辑
// 2. 使用微信支付工厂创建微信支付产品
$wechatPayFactory = new WechatPayFactory();
$wechatPay = $wechatPayFactory->createProduct();
echo $wechatPay->doService() . PHP_EOL; // 输出:微信支付:执行订单预支付、支付结果校验逻辑
// 3. 客户端可动态切换工厂(如切换支付方式)
$payFactory = new AlipayFactory(); // 可根据配置动态选择工厂
$payProduct = $payFactory->createProduct();
echo $payProduct->doService() . PHP_EOL;
} catch (\Exception $e) {
echo "错误:" . $e->getMessage();
}
核心设计说明
1. 核心结构拆解
// 1. 产品接口:定义所有产品的统一方法,保证产品一致性
interface ProductInterface
{
public function doService(): string;
}
// 2. 具体产品类:实现产品接口,封装自身业务逻辑(可包含专属属性/方法)
class AlipayProduct implements ProductInterface
{
public function doService(): string { /* 业务逻辑 */ }
}
// 3. 抽象工厂接口:定义创建产品的统一方法,规范工厂行为
interface FactoryInterface
{
public function createProduct(): ProductInterface;
}
// 4. 具体工厂类:实现抽象工厂接口,负责对应产品的创建和初始化
class AlipayFactory implements FactoryInterface
{
public function createProduct(): ProductInterface
{
// 产品专属初始化逻辑
return new AlipayProduct();
}
}
2. 关键优化点(对比基础实现)
// 优化1:引入抽象工厂接口,强制所有工厂遵循统一规范,便于客户端调用
interface FactoryInterface
{
public function createProduct(): ProductInterface;
}
// 优化2:具体工厂封装产品专属初始化逻辑,职责单一且内聚
private function initAlipayConfig(): void
{
// 产品初始化逻辑(如加载配置、初始化依赖),不暴露给客户端
}
// 优化3:明确类型声明(返回值为 ProductInterface),增强类型安全和可读性
public function createProduct(): ProductInterface
// 优化4:遵循开闭原则,新增产品无需修改原有工厂,仅需扩展子类
// 新增产品C(ApplePay)时,仅需新增 ApplePayProduct 和 ApplePayFactory
// 优化5:客户端依赖抽象层,可通过切换工厂子类动态切换产品,灵活性更强
$payFactory = new AlipayFactory(); // 切换为 WechatPayFactory 即可换产品
3. 常见错误规避
// 错误1:未定义抽象工厂接口,直接创建具体工厂,客户端依赖具体实现,耦合度高
// 解决:定义 FactoryInterface,所有具体工厂实现该接口
// 错误2:具体工厂包含多种产品创建逻辑,违背单一职责原则
// 解决:一个具体工厂仅负责一种产品的创建,新增产品对应新增工厂
// 错误3:产品类无统一接口,工厂返回不同类型产品,客户端调用混乱
// 解决:强制所有产品实现 ProductInterface,工厂统一返回该接口类型
// 错误4:将产品初始化逻辑放在客户端,导致客户端与产品耦合
// 解决:将初始化逻辑封装在具体工厂中,客户端仅调用工厂的 createProduct() 方法
补充说明
1. 扩展场景示例(新增产品)
若需新增 ApplePay 支付产品,仅需扩展两个类,无需修改原有代码,完全遵循开闭原则:
// 1. 新增具体产品类(实现产品接口)
class ApplePayProduct implements ProductInterface
{
public function doService(): string
{
return "ApplePay支付:执行生物识别验证、支付扣款逻辑";
}
}
// 2. 新增具体工厂类(实现工厂接口)
class ApplePayFactory implements FactoryInterface
{
public function createProduct(): ProductInterface
{
// ApplePay专属初始化逻辑(如加载证书、初始化SDK)
$this->initApplePayConfig();
return new ApplePayProduct();
}
private function initApplePayConfig(): void
{
// 模拟加载ApplePay配置
}
}
// 客户端使用(无需修改原有代码)
$applePayFactory = new ApplePayFactory();
$applePay = $applePayFactory->createProduct();
echo $applePay->doService();
2. 实际应用场景
-
多支付方式集成(支付宝/微信/ApplePay/银行卡),支持动态切换;
-
日志驱动扩展(文件日志/数据库日志/Redis日志/ELK日志);
-
缓存适配器管理(本地缓存/Redis缓存/Memcached缓存);
-
消息推送渠道(短信/邮件/微信公众号/APP推送)。
简单工厂模式与工厂模式对比表
| 对比维度 | 简单工厂模式 | 工厂模式(工厂方法) |
|---|---|---|
| 核心结构 | 一个静态工厂类 + 多个具体产品(无抽象工厂) | 抽象工厂接口 + 多个具体工厂 + 多个具体产品(一对一对应) |
| 开闭原则 | 不遵循:新增产品需修改工厂类的判断逻辑(如添加case分支) | 遵循:新增产品仅需扩展具体产品和工厂子类,无需修改原有代码 |
| 类数量 | 少:仅需1个工厂类,产品类按需增加 | 多:每新增1个产品,需对应新增1个工厂子类,可能导致类膨胀 |
| 创建逻辑位置 | 集中在一个工厂类中,由工厂根据参数判断创建哪种产品 | 分散在各个具体工厂中,每个工厂仅负责创建一种产品,无判断逻辑 |
| 客户端依赖 | 依赖具体工厂类和抽象产品(或具体产品) | 仅依赖抽象工厂和抽象产品,完全解耦具体实现 |
| 灵活性 | 较低:切换产品需修改客户端传入的参数,扩展受限 | 较高:切换产品仅需替换具体工厂子类,支持动态扩展和切换 |
| 适用场景 | 产品数量少、变动少,追求简洁性(如3-5个同类产品) | 产品数量多、可能持续扩展,追求扩展性(如超过5个同类产品) |
| 维护成本 | 低:类数量少,逻辑集中,适合小型场景 | 中:类数量多,但职责清晰,扩展时维护成本低,适合中大型场景 |
| 初始化逻辑 | 所有产品的初始化逻辑集中在一个工厂,易冗余 | 每个产品的初始化逻辑封装在对应工厂,职责内聚,清晰易维护 |


