PHP 对象池模式
什么是对象池
对象池设计模式 是一种创建型设计模式。它使用一组提前已准备完成可以使用的对象,而不是根据需要分配或销毁。这种来源被称为:“池”(pool)。池的使用者将从池中请求一个对象,并对返回的对象进行操作。在客户端处理完成后,它将返回一种特定类型的工厂对象。返回给池,而不是销毁。
对象池模式在一些情景下可以带来明显的性能提升。如:类实例初始化成本较高、类的实例化率较高、或类实例同时使用率不高的情况下。当创建新对象(尤其是通过网络)的时间花费不确定时,池对象的获得时间却是可预测的。
这些优点对于时间要求敏感的对象来说,是非常有用的。例如:数据库连接、套接字连接、线程和大型图形对象(如字体或位图)。但在某些情况下,简单的对象池(不包含外部资源,只占用内存)可能效率不高,并且会降低性能。
1.4.2. UML 图
1.4.3. 代码
WorkerPool.php
<?php
declare(strict_types=1);
namespace DesignPatterns\Creational\Pool;
use Countable;
class WorkerPool implements Countable
{
/**
* @var StringReverseWorker[]
*/
private array $occupiedWorkers = [];
/**
* @var StringReverseWorker[]
*/
private array $freeWorkers = [];
public function get(): StringReverseWorker
{
if (count($this->freeWorkers) == 0) {
$worker = new StringReverseWorker();
} else {
$worker = array_pop($this->freeWorkers);
}
$this->occupiedWorkers[spl_object_hash($worker)] = $worker;
return $worker;
}
public function dispose(StringReverseWorker $worker)
{
$key = spl_object_hash($worker);
if (isset($this->occupiedWorkers[$key])) {
unset($this->occupiedWorkers[$key]);
$this->freeWorkers[$key] = $worker;
}
}
public function count(): int
{
return count($this->occupiedWorkers) + count($this->freeWorkers);
}
}
StringReverseWorker.php
<?php declare(strict_types=1); namespace DesignPatterns\Creational\Pool; use DateTime; class StringReverseWorker { public function __construct() { } public function run(string $text): string { return strrev($text); } }
测试
Tests/PoolTest.php
<?php declare(strict_types=1); namespace DesignPatterns\Creational\Pool\Tests; use DesignPatterns\Creational\Pool\WorkerPool; use PHPUnit\Framework\TestCase; class PoolTest extends TestCase { public function testCanGetNewInstancesWithGet() { $pool = new WorkerPool(); $worker1 = $pool->get(); $worker2 = $pool->get(); $this->assertCount(2, $pool); $this->assertNotSame($worker1, $worker2); } public function testCanGetSameInstanceTwiceWhenDisposingItFirst() { $pool = new WorkerPool(); $worker1 = $pool->get(); $pool->dispose($worker1); $worker2 = $pool->get(); $this->assertCount(1, $pool); $this->assertSame($worker1, $worker2); } }