本文目录导读:

是的,你的理解完全正确。PHP享元模式(Flyweight Pattern)的核心目的就是共享细粒度对象。
它通过将对象的状态区分为内部状态和外部状态来实现共享:
核心机制
- 内部状态(Intrinsic State):存储在享元对象内部,并且不会随环境改变而改变,这部分是可以被共享的,一个文字处理软件中字符的“字体”和“字号”。
- 外部状态(Extrinsic State):随环境改变而改变,不可共享的状态,它通常由客户端在调用时传入享元对象,同一个字符在文档中的“位置”(x, y 坐标)。
享元模式通过一个享元工厂(Flyweight Factory)来管理一个池(通常是数组或 Map),当客户端请求一个享元对象时,工厂会检查池中是否已经存在具有相同内部状态的对象:
- 如果存在,直接返回该对象的引用。
- 如果不存在,则创建一个新的享元对象,放入池中,然后返回。
典型应用场景
- 文本编辑器:每个字符(如 ‘A’、‘B’)可以被共享,其字体、颜色作为内部状态,而字符在文档中的位置作为外部状态。
- 游戏开发:在角色扮演游戏(RPG)中,大量怪物或粒子(如树叶、火花)的外观(纹理、形状)可共享,而每个实例的坐标、血量、移动方向是外部状态。
- 数据库连接池:虽然通常不直接称为享元,但其思想一致——复用昂贵的数据库连接对象。
PHP 示例代码
<?php
// 1. 定义享元接口
interface Flyweight {
public function operation(string $externalState): void;
}
// 2. 具体享元类(包含可共享的内部状态)
class ConcreteFlyweight implements Flyweight {
private string $intrinsicState;
public function __construct(string $intrinsicState) {
$this->intrinsicState = $intrinsicState;
// 模拟创建对象开销较大
echo "创建享元对象,内部状态: {$this->intrinsicState}\n";
}
public function operation(string $externalState): void {
echo "内部状态: {$this->intrinsicState}, 外部状态: {$externalState}\n";
}
}
// 3. 享元工厂(管理池)
class FlyweightFactory {
private array $pool = [];
public function getFlyweight(string $key): Flyweight {
if (!isset($this->pool[$key])) {
$this->pool[$key] = new ConcreteFlyweight($key);
} else {
echo "复用享元对象,内部状态: {$key}\n";
}
return $this->pool[$key];
}
public function getPoolSize(): int {
return count($this->pool);
}
}
// 4. 客户端代码
$factory = new FlyweightFactory();
// 创建或获取享元对象,外部状态不同
$flyweight1 = $factory->getFlyweight('A');
$flyweight1->operation('位置1');
$flyweight2 = $factory->getFlyweight('B');
$flyweight2->operation('位置2');
// 再次请求内部状态为 'A' 的对象,将复用
$flyweight3 = $factory->getFlyweight('A');
$flyweight3->operation('位置3');
echo "池中对象数量: " . $factory->getPoolSize() . "\n"; // 输出 2,而不是 3
输出结果:
创建享元对象,内部状态: A
内部状态: A, 外部状态: 位置1
创建享元对象,内部状态: B
内部状态: B, 外部状态: 位置2
复用享元对象,内部状态: A
内部状态: A, 外部状态: 位置3
池中对象数量: 2
关键点)
| 特性 | 说明 |
|---|---|
| 共享对象 | 是,核心目的,通过工厂池复用具有相同内部状态的对象。 |
| 细粒度 | 是,享元对象通常设计得非常小,只包含少量必要且可共享的状态。 |
| 节省内存 | 主要优点,通过共享大量相似对象,显著降低内存占用(尤其在需要创建大量重复对象时)。 |
| 时间换空间? | 实际上是一种以少量计算(查找池)换取大量内存节省的经典设计。 |
“PHP享元模式共享细粒度对象” 这个说法是完全准确的,当你的 PHP 应用需要处理大量非常相似的对象并且这些对象的内存开销成为问题时,享元模式是一个非常有效的优化手段。