概述
简单工厂模式(Simple Factory Pattern)是 PHP 中最基础、最常用的创建型设计模式之一,也被称为“静态工厂模式”。
其核心目标是将对象的创建逻辑与使用逻辑分离,通过一个统一的“工厂类”负责实例化不同类型的产品对象,客户端无需关心对象的创建细节(如类名、构造参数、依赖关系),仅需通过工厂类的静态方法传入指定参数,即可获取所需实例。
核心价值
- 降低耦合:客户端与具体产品类解耦,修改产品类名或构造逻辑时,仅需修改工厂类,无需改动所有调用处;
- 简化创建:隐藏对象创建的复杂逻辑(如参数校验、依赖初始化),客户端通过简单参数即可获取实例;
- 统一管理:集中管理同类产品的创建逻辑,便于后续扩展、维护和迭代(如新增产品时仅需扩展工厂类)。
适用场景
- 产品类数量较少且逻辑相对简单(如 3-5 个同类产品);
- 客户端无需关心对象创建细节,仅需根据参数获取对应实例;
- 产品类具有共同的父类或实现统一接口(保证工厂返回实例的一致性)。
注意事项
- 不符合“开闭原则”:新增产品时需修改工厂类的判断逻辑(如添加
case分支),适用于产品变动不频繁的场景; - 避免过度设计:若产品类过多(如 10 个以上)或创建逻辑复杂,建议升级为“工厂方法模式”或“抽象工厂模式”。
完整代码
<?php
declare(strict_types = 1);
/**
* 产品接口:定义所有产品的统一规范(保证产品一致性)
* Interface ProductInterface
*/
interface ProductInterface
{
public function doService(): string;
}
/**
* 具体产品A:实现产品接口
* Class ProductA
*/
class ProductA implements ProductInterface
{
public function doService(): string
{
return "产品A:执行服务逻辑(如支付宝支付处理)";
}
}
/**
* 具体产品B:实现产品接口
* Class ProductB
*/
class ProductB implements ProductInterface
{
public function doService(): string
{
return "产品B:执行服务逻辑(如微信支付处理)";
}
}
/**
* 具体产品C:实现产品接口
* Class ProductC
*/
class ProductC implements ProductInterface
{
public function doService(): string
{
return "产品C:执行服务逻辑(如银行卡支付处理)";
}
}
/**
* 简单工厂类:统一创建所有产品实例
* Class SimpleFactory
*/
class SimpleFactory
{
/**
* 获取产品实例(静态方法,无需实例化工厂)
* @param string $productType 产品类型标识(如 'a'/'b'/'c')
* @return ProductInterface 产品实例(遵循统一接口)
* @throws \InvalidArgumentException 当产品类型不支持时抛出异常
*/
public static function createProduct(string $productType): ProductInterface
{
// 参数校验:避免无效输入
$validTypes = ['a', 'b', 'c'];
if (!in_array(strtolower($productType), $validTypes, true)) {
throw new \InvalidArgumentException(
sprintf("不支持的产品类型:%s,仅支持:%s", $productType, implode(',', $validTypes))
);
}
// 根据产品类型创建对应实例
return match (strtolower($productType)) {
'a' => new ProductA(),
'b' => new ProductB(),
'c' => new ProductC(),
};
}
}
// 测试代码
try {
// 1. 获取产品A实例并调用服务
$productA = SimpleFactory::createProduct('a');
echo $productA->doService() . PHP_EOL; // 输出:产品A:执行服务逻辑(如支付宝支付处理)
// 2. 获取产品B实例并调用服务
$productB = SimpleFactory::createProduct('B'); // 支持大小写不敏感
echo $productB->doService() . PHP_EOL; // 输出:产品B:执行服务逻辑(如微信支付处理)
// 3. 获取产品C实例并调用服务
$productC = SimpleFactory::createProduct('c');
echo $productC->doService() . PHP_EOL; // 输出:产品C:执行服务逻辑(如银行卡支付处理)
// 4. 测试无效产品类型(会抛出异常)
// $invalidProduct = SimpleFactory::createProduct('d');
} catch (\InvalidArgumentException $e) {
echo "错误:" . $e->getMessage();
}
核心设计说明
1. 核心结构拆解
// 1. 产品接口:定义统一规范,确保所有产品具有一致的方法
interface ProductInterface
{
public function doService(): string;
}
// 2. 具体产品类:实现产品接口,封装自身业务逻辑
class ProductA implements ProductInterface
{
public function doService(): string { /* 业务逻辑 */ }
}
// 3. 工厂类:静态方法接收参数,创建并返回对应产品实例
class SimpleFactory
{
public static function createProduct(string $productType): ProductInterface
{
// 参数校验 + 实例化逻辑
}
}
2. 关键优化点(对比基础实现)
// 优化1:引入产品接口,强制所有产品遵循统一规范,提升代码一致性
interface ProductInterface { /* 统一方法定义 */ }
// 优化2:添加参数校验,避免无效输入导致的逻辑错误
$validTypes = ['a', 'b', 'c'];
if (!in_array(strtolower($productType), $validTypes, true)) {
throw new \InvalidArgumentException("不支持的产品类型");
}
// 优化3:使用 match 表达式(PHP 8.0+)替代 switch,代码更简洁高效
return match (strtolower($productType)) {
'a' => new ProductA(),
'b' => new ProductB(),
'c' => new ProductC(),
};
// 优化4:支持产品类型大小写不敏感,提升使用灵活性
strtolower($productType);
// 优化5:明确返回类型声明(ProductInterface),增强代码可读性和类型安全性
public static function createProduct(string $productType): ProductInterface
3. 常见错误规避
// 错误1:未定义产品接口,产品类无统一规范,后续扩展易混乱
// 解决:强制所有产品实现 ProductInterface
// 错误2:缺少参数校验,传入无效类型时返回 null 或报错不明确
// 解决:添加 in_array 校验,抛出具体的 InvalidArgumentException
// 错误3:使用硬编码类名,修改产品类名时需多处改动
// 解决:集中在工厂类管理,修改仅需改工厂类的 match 分支
// 错误4:工厂方法非静态,需实例化工厂才能使用,冗余繁琐
// 解决:工厂方法设为 static,直接通过类名调用(SimpleFactory::createProduct())
补充说明
-
PHP 版本适配:
-
代码中
match表达式需 PHP 8.0 及以上版本; -
如果使用 PHP 8.0 以下版本,可替换为
switch语句:switch (strtolower($productType)) { case 'a': return new ProductA(); case 'b': return new ProductB(); case 'c': return new ProductC(); default: throw new \InvalidArgumentException("不支持的产品类型"); }
-
-
扩展场景示例:
如果需要新增产品 D,仅需两步操作(虽然修改工厂类,但简单高效):
// 1. 新增产品类并实现接口 class ProductD implements ProductInterface { public function doService(): string { return "产品D:执行服务逻辑(如ApplePay支付处理)"; } } // 2. 工厂类中添加对应分支 return match (strtolower($productType)) { 'a' => new ProductA(), 'b' => new ProductB(), 'c' => new ProductC(), 'd' => new ProductD(), // 新增分支 default: throw new \InvalidArgumentException(...); }; -
实际应用场景:
-
支付方式选择(支付宝/微信/银行卡/ApplePay);
-
日志驱动切换(文件日志/数据库日志/Redis日志);
-
缓存适配器创建(本地缓存/Redis缓存/Memcached缓存)。
-


