1.4. Pool
1.4.1. Purpose
** Шаблонът за обект на обекти ** е софтуерен шаблон за създаване на дизайн, който използва набор от инициализирани обекти, поддържани в готовност за използване - „пул“ - вместо да ги разпределя и унищожава при поискване. Клиент на пула ще поиска обект от пула и ще извърши операции върху върнатия обект. Когато клиентът завърши, той връща обекта, който е специфичен тип фабричен обект, в пула, вместо да го унищожава.
Обединяването на обекти може да предложи значително подобрение на производителността в ситуации, когато цената за инициализиране на екземпляр на клас е висока, скоростта на създаване на екземпляр на клас е висока и броят на използваните екземпляри по всяко време е нисък. Обединеният обект се получава в предвидимо време, когато създаването на новите обекти (особено по мрежа) може да отнеме променливо време.
Тези предимства обаче важат най-вече за обекти, които са скъпи по отношение на времето, като връзки към база данни, връзки на сокети, нишки и големи графични обекти като шрифтове или растерни изображения. В определени ситуации простото обединяване на обекти (които не съдържат външни ресурси, а само заемат памет) може да не е ефективно и да намали производителността.
1.4.2. UML Диаграма

1.4.3. Код
Можете също да намерите този код в GitHub
WorkerPool.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Creational\Pool;
6
7use Countable;
8
9class WorkerPool implements Countable
10{
11 /**
12 * @var StringReverseWorker[]
13 */
14 private array $occupiedWorkers = [];
15
16 /**
17 * @var StringReverseWorker[]
18 */
19 private array $freeWorkers = [];
20
21 public function get(): StringReverseWorker
22 {
23 if (count($this->freeWorkers) === 0) {
24 $worker = new StringReverseWorker();
25 } else {
26 $worker = array_pop($this->freeWorkers);
27 }
28
29 $this->occupiedWorkers[spl_object_hash($worker)] = $worker;
30
31 return $worker;
32 }
33
34 public function dispose(StringReverseWorker $worker): void
35 {
36 $key = spl_object_hash($worker);
37 if (isset($this->occupiedWorkers[$key])) {
38 unset($this->occupiedWorkers[$key]);
39 $this->freeWorkers[$key] = $worker;
40 }
41 }
42
43 public function count(): int
44 {
45 return count($this->occupiedWorkers) + count($this->freeWorkers);
46 }
47}
StringReverseWorker.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Creational\Pool;
6
7class StringReverseWorker
8{
9 public function run(string $text): string
10 {
11 return strrev($text);
12 }
13}
1.4.4. Тест
Tests/PoolTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Creational\Pool\Tests;
6
7use DesignPatterns\Creational\Pool\WorkerPool;
8use PHPUnit\Framework\TestCase;
9
10class PoolTest extends TestCase
11{
12 public function testCanGetNewInstancesWithGet()
13 {
14 $pool = new WorkerPool();
15 $worker1 = $pool->get();
16 $worker2 = $pool->get();
17
18 $this->assertCount(2, $pool);
19 $this->assertNotSame($worker1, $worker2);
20 }
21
22 public function testCanGetSameInstanceTwiceWhenDisposingItFirst()
23 {
24 $pool = new WorkerPool();
25 $worker1 = $pool->get();
26 $pool->dispose($worker1);
27 $worker2 = $pool->get();
28
29 $this->assertCount(1, $pool);
30 $this->assertSame($worker1, $worker2);
31 }
32}