1.5. 풀 (Pool)¶
**오브젝트 풀 패턴**은 소프트웨어 생성 패턴(Creational Patterns) 중 하나입니다. 객체들을 하나하나 할당(Allocating)하고 해제(Destroying)하기 보다는, 풀(Pool)을 이용하여 사용할 준비가 된 초기화된 객체들을 사용합니다. 풀의 사용자(Client)는 풀에서 객체를 요청하고, 반환된 객체를 이용해서 작업을 수행합니다. 그리고 사용자가 작업을 끝내면 그것을 해제(Destroy)하기 보다는 풀에 팩토리 객체의 특정 타입으로 된 객체를 반환합니다.
객체 풀링(Pooling)은 클래스를 초기화 하는 비용이 크고, 클래스의 인스턴스화 비율이 크고, 특정 시점에 사용중인 인스턴스의 숫자가 적을 때 성능향상을 제공합니다. 풀된 객체는 새로운 객체의 생성(특히 네트워크를 통해)이 다양한 시간(오래 걸리든, 짧게 걸리든)을 갖더라도, 예측가능한 시간을 얻을 수 있습니다.
그러나, 이러한 장점들은 시간상에서 비용이 큰 객체, 이를테면 데이터베이스 연결이나, 소켓 연결, 스레드나 폰트 혹은 비트맵과 같은 큰 그래픽 객체에 대해서는 사실입니다만, 특정 상황, 즉, 단순한 객체 풀링(외부 자원은 보유하지만, 전용 메모리를 차지하는)은 아마도 효과적이지 않을 수 있고 오히려 성능을 감소시킬 수 있습니다.
1.5.1. UML 다이어그램¶
1.5.2. 코드¶
코드는 또한 GitHub 에서 볼 수 있습니다.
Pool.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?php
namespace DesignPatterns\Creational\Pool;
class Pool
{
private $instances = array();
private $class;
public function __construct($class)
{
$this->class = $class;
}
public function get()
{
if (count($this->instances) > 0) {
return array_pop($this->instances);
}
return new $this->class();
}
public function dispose($instance)
{
$this->instances[] = $instance;
}
}
|
Processor.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <?php
namespace DesignPatterns\Creational\Pool;
class Processor
{
private $pool;
private $processing = 0;
private $maxProcesses = 3;
private $waitingQueue = [];
public function __construct(Pool $pool)
{
$this->pool = $pool;
}
public function process($image)
{
if ($this->processing++ < $this->maxProcesses) {
$this->createWorker($image);
} else {
$this->pushToWaitingQueue($image);
}
}
private function createWorker($image)
{
$worker = $this->pool->get();
$worker->run($image, array($this, 'processDone'));
}
public function processDone($worker)
{
$this->processing--;
$this->pool->dispose($worker);
if (count($this->waitingQueue) > 0) {
$this->createWorker($this->popFromWaitingQueue());
}
}
private function pushToWaitingQueue($image)
{
$this->waitingQueue[] = $image;
}
private function popFromWaitingQueue()
{
return array_pop($this->waitingQueue);
}
}
|
Worker.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?php
namespace DesignPatterns\Creational\Pool;
class Worker
{
public function __construct()
{
// let's say that constuctor does really expensive work...
// for example creates "thread"
}
public function run($image, array $callback)
{
// do something with $image...
// and when it's done, execute callback
call_user_func($callback, $this);
}
}
|
1.5.3. 테스트¶
Tests/PoolTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?php
namespace DesignPatterns\Creational\Pool\Tests;
use DesignPatterns\Creational\Pool\Pool;
class PoolTest extends \PHPUnit_Framework_TestCase
{
public function testPool()
{
$pool = new Pool('DesignPatterns\Creational\Pool\Tests\TestWorker');
$worker = $pool->get();
$this->assertEquals(1, $worker->id);
$worker->id = 5;
$pool->dispose($worker);
$this->assertEquals(5, $pool->get()->id);
$this->assertEquals(1, $pool->get()->id);
}
}
|
Tests/TestWorker.php
1 2 3 4 5 6 7 8 | <?php
namespace DesignPatterns\Creational\Pool\Tests;
class TestWorker
{
public $id = 1;
}
|