multiton Пул одинаків (англ. 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);
        }
    }