Пул одиночек (англ. Multiton) - похож на шаблон Одиночка.
Позволяет создавать и содержать несколько одиночек, доступ к которым можно получить по уникальному “ключу”.
Продолжаем тему нашей закусочной. Бизнес идёт в гору, и мы устанавливаем ещё пару кассовых аппаратов.
Для удобного доступа ко всем аппаратам мы создадим систему ShopCashSystem
, которую и реализует наш Multiton.
Как и с Singleton‘ом, мы закрыли все магические методы. Для доступа к объекту используется
статический метод ShopCashSystem::getInstance()
.
Применение:
- Два объекта для доступа к базам данных, к примеру, один для MySQL, а второй для SQLite
- Несколько логирующих объектов (один для отладочных сообщений, другой для ошибок и т.п.)
Примечание: Иногда этот шаблон называют Реестр одиночек. Напомню про антипаттерн Одиночество (Singletonitis).
-
MultitonInterface.php
<?php namespace DesignPatterns\Creational\Multiton; /** * Interface MultitonInterface * @package DesignPatterns\Creational\Multiton */ interface MultitonInterface { /** * @param string $instanceName * * @return MultitonInterface */ public static function getInstance(string $instanceName): self; }
-
ShopCashSystem.php
<?php namespace DesignPatterns\Creational\Multiton; use DesignPatterns\Creational\Singleton\CashboxTrait; /** * Class ShopCashSystem * @package DesignPatterns\Creational\Multiton */ class ShopCashSystem implements MultitonInterface { use CashboxTrait; /** * @var MultitonInterface[] */ private static $instances = []; /** * Return Singleton instance * * @param string $instanceName * * @return MultitonInterface */ public static function getInstance(string $instanceName): MultitonInterface { if (!isset(self::$instances[$instanceName])) { self::$instances[$instanceName] = new self(); } return self::$instances[$instanceName]; } private function __construct() { } private function __clone() { } private function __wakeup() { } }
Test case:
MultitonTest.php
<?php
namespace DesignPatterns\Tests\Creational\Multiton;
use DesignPatterns\Creational\Multiton\ShopCashSystem;
use PHPUnit_Framework_TestCase;
class MultitonTest extends PHPUnit_Framework_TestCase
{
public function testUniqueness()
{
$firstCashbox = ShopCashSystem::getInstance('Cashbox#1');
$secondCashbox = ShopCashSystem::getInstance('Cashbox#2');
$this->assertInstanceOf('DesignPatterns\Creational\Multiton\MultitonInterface', $firstCashbox);
$this->assertInstanceOf('DesignPatterns\Creational\Multiton\MultitonInterface', $secondCashbox);
$this->assertNotSame($firstCashbox, $secondCashbox);
$thirdCashbox = ShopCashSystem::getInstance('Cashbox#1');
$this->assertSame($firstCashbox, $thirdCashbox);
$firstCashbox->setCash(5);
$this->assertSame($firstCashbox, $thirdCashbox);
}
}