本文目录导读:

在PHP项目中,“蝇量模式”(Flyweight Pattern)和“共享对象”(Shared Object)是两种不同的概念,但它们在解决内存和性能问题上有关联。
🪶 1. 蝇量模式 (Flyweight Pattern)
核心思想
通过共享相同状态的对象来减少内存使用,适用于系统中存在大量细粒度对象、且这些对象可以拆分为内部状态(共享)和外部状态(不共享)的场景。
在 PHP 中的实现
// 1. 定义蝇量接口
interface CharacterFlyweight {
public function render(string $externalState): string;
}
// 2. 共享对象(内部状态:字体样式)
class ConcreteCharacter implements CharacterFlyweight {
private string $fontFamily;
private int $fontSize;
public function __construct(string $fontFamily, int $fontSize) {
$this->fontFamily = $fontFamily;
$this->fontSize = $fontSize;
}
public function render(string $character): string {
return sprintf(
"<span style='font-family:%s; font-size:%dpx'>%s</span>",
$this->fontFamily,
$this->fontSize,
$character
);
}
}
// 3. 工厂(管理共享对象池)
class CharacterFactory {
private array $pool = [];
public function getCharacter(string $fontFamily, int $fontSize): CharacterFlyweight {
$key = md5("{$fontFamily}_{$fontSize}");
if (!isset($this->pool[$key])) {
$this->pool[$key] = new ConcreteCharacter($fontFamily, $fontSize);
}
return $this->pool[$key];
}
}
// 4. 客户端使用
$factory = new CharacterFactory();
$characters = ['A', 'B', 'C', 'A', 'B', 'A'];
// 即使渲染多个字符,字体对象只生成 3 个
$renderResults = [];
foreach ($characters as $char) {
$flyweight = $factory->getCharacter('Arial', 12); // 共享同一个字体对象
$renderResults[] = $flyweight->render($char);
}
📦 2. 共享对象 (Shared Object)
在 PHP 中,“共享对象”可以指不同层面的概念:
a. 对象池模式(Object Pool)
与蝇量模式不同,对象池的核心是复用创建成本高的对象(如数据库连接、大对象)。
class ConnectionPool {
private array $available = [];
private array $inUse = [];
public function getConnection(): PDO {
if (empty($this->available)) {
// 创建新连接(成本高)
$conn = new PDO("mysql:host=localhost;dbname=test", "user", "pass");
} else {
$conn = array_pop($this->available);
}
$this->inUse[spl_object_id($conn)] = $conn;
return $conn;
}
public function release(PDO $conn): void {
$id = spl_object_id($conn);
if (isset($this->inUse[$id])) {
unset($this->inUse[$id]);
$this->available[] = $conn;
}
}
}
b. 共享变量/状态(多进程/多线程)
PHP-FPM 模式下,不同请求之间无法直接共享对象,但可以通过:
- APCu / Redis / Memcached 存储序列化对象
- Swoole 协程 共享内存
- 共享扩展(如
shmop操作共享内存块)
// APCu 示例
apcu_store('shared_config', ['db_host' => 'localhost']);
$config = apcu_fetch('shared_config');
c. 单例模式(进程内共享)
确保一个类只有一个实例,在当前 PHP 进程内共享:
class DBConnection {
private static ?self $instance = null;
private PDO $pdo;
private function __construct() { /* 初始化连接 */ }
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
🆚 对比:蝇量模式 vs 共享对象
| 特性 | 蝇量模式 | 共享对象(对象池) |
|---|---|---|
| 目的 | 减少内存(对象数量) | 复用创建成本 |
| 核心机制 | 将对象拆分为内部/外部状态 | 预创建 + 循环使用 |
| 适用场景 | 大量相似对象(如字符、粒子) | 昂贵资源(连接、线程) |
| 对象属性 | 不可变内部状态(共享) | 可被重置 |
| 生命周期 | 长期存在(池化管理) | 受池容量限制 |
| PHP 典型例子 | 文本渲染、游戏粒子系统 | 数据库连接池 |
🧠 实战建议
- 使用蝇量模式的前提:对象数量非常大(>1000)且对象可拆分为共享/非共享部分。
- 对象池的应用:在数据库、HTTP客户端、大型计算结果缓存中非常有效。
- 注意线程安全:Swoole 协程环境下共享对象需加锁。
- 性能权衡:共享对象节省了创建时间但增加了管理开销,需要根据业务场景选择合适的实现。
📚 代码示例链接(GitHub)
需要我针对某个具体场景给出更详细的实现吗?
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播