1.5.1. 目的
對(duì)象池模式是一種提前準(zhǔn)備了一組已經(jīng)初始化了的對(duì)象『池』而不是按需創(chuàng)建或者銷毀的創(chuàng)建型設(shè)計(jì)模式。對(duì)象池的客戶端會(huì)向?qū)ο蟪刂姓?qǐng)求一個(gè)對(duì)象透罢,然后使用這個(gè)返回的對(duì)象執(zhí)行相關(guān)操作。當(dāng)客戶端使用完畢季希,它將把這個(gè)特定類型的工廠對(duì)象返回給對(duì)象池蔬咬,而不是銷毀掉這個(gè)對(duì)象曹动。
在初始化實(shí)例成本高叹放,實(shí)例化率高饰恕,可用實(shí)例不足的情況下,對(duì)象池可以極大地提升性能井仰。在創(chuàng)建對(duì)象(尤其是通過(guò)網(wǎng)絡(luò))時(shí)間花銷不確定的情況下懂盐,通過(guò)對(duì)象池在可期時(shí)間內(nèi)就可以獲得所需的對(duì)象。
無(wú)論如何糕档,對(duì)象池模式在需要耗時(shí)創(chuàng)建對(duì)象方面,例如創(chuàng)建數(shù)據(jù)庫(kù)連接拌喉,套接字連接速那,線程和大型圖形對(duì)象(比方字體或位圖等),使用起來(lái)都是大有裨益的尿背。在某些情況下端仰,簡(jiǎn)單的對(duì)象池(無(wú)外部資源,只占內(nèi)存)可能效率不高田藐,甚至?xí)袚p性能荔烧。
1.5.2. UML 類圖
1.5.3. 代碼
你可以在?GitHub?上找到這些例子
WorkerPool.php
<?php
namespace DesignPatterns\Creational\Pool;
class WorkerPool implements \Countable
{
/**
* @var StringReverseWorker[]
*/
private $occupiedWorkers = [];
/**
* @var StringReverseWorker[]
*/
private $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
namespace DesignPatterns\Creational\Pool;
class StringReverseWorker
{
/**
* @var \DateTime
*/
private $createdAt;
public function __construct()
{
$this->createdAt = new \DateTime();
}
public function run(string $text)
{
return strrev($text);
}
}
1.5.4. 測(cè)試
Tests/PoolTest.php
<?php
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);
}
}