對象池設(shè)計模式 是一種創(chuàng)建型設(shè)計模式。它使用一組提前已準(zhǔn)備完成可以使用的對象,而不是根據(jù)需要分配或銷毀。這種來源被稱為:“池”(pool)。池的使用者將從池中請求一個對象,并對返回的對象進(jìn)行操作。在客戶端處理完成后,它將返回一種特定類型的工廠對象。返回給池,而不是銷毀。
對象池模式在一些情景下可以帶來明顯的性能提升。如:類實例初始化成本較高、類的實例化率較高、或類實例同時使用率不高的情況下。當(dāng)創(chuàng)建新對象(尤其是通過網(wǎng)絡(luò))的時間花費不確定時,池對象的獲得時間卻是可預(yù)測的。
這些優(yōu)點對于時間要求敏感的對象來說,是非常有用的。例如:數(shù)據(jù)庫連接、套接字連接、線程和大型圖形對象(如字體或位圖)。但在某些情況下,簡單的對象池(不包含外部資源,只占用內(nèi)存)可能效率不高,并且會降低性能。
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); } }
更多建議: