工厂模式的核心思想是将对象的创建过程封装到独立的工厂类中,让客户端无需直接依赖具体类的构造函数,而是通过工厂接口获取所需实例。PHP 8.3的多个新特性能够从语法简化、类型安全、性能提升等维度优化工厂模式的实现。

PHP 8.3相关新特性概述
在讨论优化效果前,先梳理几个和工厂模式优化强相关的PHP 8.3新特性:
- 只读类(Readonly Classes):使用
readonly修饰的类,其所有属性默认只读,且类本身不可被继承,适合定义不可变的产品类。 - 类型安全的交叉类型(Intersection Types)增强:支持更灵活的类型约束,可在工厂方法中约束返回对象必须同时满足多个接口要求。
- 动态类常量获取优化:支持更简洁的语法获取类的常量值,简化工厂中基于常量判断创建逻辑的实现。
- JIT编译优化升级:新的JIT实现提升了短生命周期对象的创建性能,而工厂模式正是频繁创建对象的场景。
传统工厂模式的实现痛点
先看一个传统的简单工厂模式实现,假设我们需要创建不同支付渠道的支付实例:
<?php
// 支付接口
interface PaymentInterface {
public function pay(float $amount): string;
}
// 微信支付实现
class WechatPay implements PaymentInterface {
private string $appId;
private string $secret;
public function __construct(string $appId, string $secret) {
$this->appId = $appId;
$this->secret = $secret;
}
public function pay(float $amount): string {
return "微信支付{$amount}元,appId:{$this->appId}";
}
}
// 支付宝支付实现
class Alipay implements PaymentInterface {
private string $merchantId;
private string $key;
public function __construct(string $merchantId, string $key) {
$this->merchantId = $merchantId;
$this->key = $key;
}
public function pay(float $amount): string {
return "支付宝支付{$amount}元,商户号:{$this->merchantId}";
}
}
// 传统简单工厂
class PaymentFactory {
public static function create(string $type, array $config): PaymentInterface {
switch ($type) {
case 'wechat':
return new WechatPay($config['appId'], $config['secret']);
case 'alipay':
return new Alipay($config['merchantId'], $config['key']);
default:
throw new InvalidArgumentException("不支持的支付类型:{$type}");
}
}
}
// 使用示例
$pay = PaymentFactory::create('wechat', ['appId' => 'wx123', 'secret' => 'sec456']);
echo $pay->pay(100);
?>
传统实现存在几个明显问题:产品类的属性没有强制只读约束,可能被意外修改;工厂方法的返回类型仅约束了接口,无法更细粒度约束;配置参数传递依赖数组,缺少类型校验;频繁创建对象时性能没有针对性优化。
PHP 8.3新特性对工厂模式的优化
1. 用只读类定义不可变产品类
支付类的配置属性在初始化后通常不需要修改,使用PHP 8.3的只读类可以避免属性被意外篡改,同时明确类的不可变语义:
<?php
readonly class WechatPay implements PaymentInterface {
public function __construct(
private string $appId,
private string $secret
) {}
public function pay(float $amount): string {
return "微信支付{$amount}元,appId:{$this->appId}";
}
}
readonly class Alipay implements PaymentInterface {
public function __construct(
private string $merchantId,
private string $key
) {}
public function pay(float $amount): string {
return "支付宝支付{$amount}元,商户号:{$this->merchantId}";
}
}
?>
只读类会自动将所有属性设为只读,且类不能被继承,既减少了手动写private set的冗余代码,也提升了代码的安全性。
2. 交叉类型约束工厂返回对象
如果某个产品需要同时满足多个接口的要求,PHP 8.3的交叉类型可以在工厂方法中直接约束,避免返回不符合要求的对象:
<?php
interface Loggable {
public function log(string $message): void;
}
// 假设某个支付类同时需要实现支付和日志接口
class WechatPayV2 extends WechatPay implements Loggable {
public function log(string $message): void {
echo "微信支付日志:{$message}";
}
}
// 工厂方法使用交叉类型约束
class PaymentFactory {
public static function createLoggablePay(string $type, array $config): PaymentInterface&Loggable {
// 只有同时实现两个接口的对象才能返回
$instance = self::create($type, $config);
if (!$instance instanceof Loggable) {
throw new RuntimeException("该支付类型不支持日志功能");
}
return $instance;
}
}
?>
交叉类型PaymentInterface&Loggable明确了返回对象必须同时实现两个接口,编译期就能做类型检查,比运行期判断更可靠。
3. 动态类常量简化工厂判断逻辑
如果产品类型对应类的常量,PHP 8.3优化后的动态类常量语法可以简化工厂的类型判断:
<?php
class PaymentType {
const WECHAT = 'WechatPay';
const ALIPAY = 'Alipay';
}
class PaymentFactory {
public static function create(string $type, array $config): PaymentInterface {
// 直接拼接类名获取常量,简化判断逻辑
$className = PaymentType::{$type} ?? throw new InvalidArgumentException("不支持的支付类型:{$type}");
// 假设构造函数参数统一用配置数组,结合PHP 8.3的构造函数属性提升简化
return new $className(...$config);
}
}
?>
这种写法避免了冗长的switch判断,后续新增支付类型只需要在PaymentType类中添加常量即可,符合开闭原则。
4. JIT优化提升对象创建性能
PHP 8.3的JIT编译优化对短生命周期对象的创建性能有显著提升,工厂模式频繁创建产品对象的场景下,无需修改代码就能获得性能收益。可以通过简单的测试验证:
<?php
$start = microtime(true);
for ($i = 0; $i < 100000; $i++) {
PaymentFactory::create('wechat', ['appId' => 'wx123', 'secret' => 'sec456']);
}
$end = microtime(true);
echo "创建10万个对象耗时:" . ($end - $start) . "秒";
?>
在PHP 8.3环境下运行该测试,相比PHP 8.2会有明显的耗时降低,对于高并发场景下的工厂模式使用非常友好。
优化后的完整工厂模式示例
结合上述新特性,优化后的工厂模式实现如下:
<?php
interface PaymentInterface {
public function pay(float $amount): string;
}
readonly class WechatPay implements PaymentInterface {
public function __construct(
private string $appId,
private string $secret
) {}
public function pay(float $amount): string {
return "微信支付{$amount}元,appId:{$this->appId}";
}
}
readonly class Alipay implements PaymentInterface {
public function __construct(
private string $merchantId,
private string $key
) {}
public function pay(float $amount): string {
return "支付宝支付{$amount}元,商户号:{$this->merchantId}";
}
}
class PaymentType {
const WECHAT = WechatPay::class;
const ALIPAY = Alipay::class;
}
class PaymentFactory {
public static function create(string $type, array $config): PaymentInterface {
$className = PaymentType::{$type} ?? throw new InvalidArgumentException("不支持的支付类型:{$type}");
return new $className(...$config);
}
}
// 使用示例
$pay = PaymentFactory::create('WECHAT', ['appId' => 'wx123', 'secret' => 'sec456']);
echo $pay->pay(100);
?>
优化后的代码减少了冗余判断,类型约束更严格,安全性更高,同时还能享受PHP 8.3运行时的性能提升,充分体现了新特性对工厂模式的优化价值。