flyweight Пристосуванець (англ. Flyweight, “легковажний (елемент)”) — структурний шаблон проєктування, при якому об’єкт, який представляє себе як унікальний екземпляр у різних місцях програми, за фактом не є таким.

Сам шаблон дуже простий. У минулому прикладі ми генерували звіт. Як і будь-який документ, наш звіт можна розбити на компоненти. Назва, контент, підпис, друк тощо. Як бачимо, багато компонентів можуть повторюватися, а відмінність їх буде лише в стані. Кожна ініціалізація нового об’єкта використовує n ресурсу. І рано чи пізно ми можемо досягти межі. Даний шаблон дає нам можливість використовувати повторно той самий компонент системи, лише змінюючи його стан.

  • Factory.php
                  
    <?php
    
    namespace DesignPatterns\Structural\Flyweight;
    
    use Countable;
    
    /**
     * Class Factory
     * @package DesignPatterns\Structural\Flyweight
     */
    class Factory implements Countable
    {
        /**
         * @var array
         */
        protected $pool = [];
    
        /**
         * @param string $name
         *
         * @return TitleFlyweightInterface
         */
        public function get(string $name): TitleFlyweightInterface
        {
            if (!isset($this->pool[$name])) {
                $this->pool[$name] = new Title($name);
            }
    
            return $this->pool[$name];
        }
    
        /**
         * @return int
         */
        public function count(): int
        {
            return count($this->pool);
        }
    }
    
                  
  • Title.php
                  
    <?php
    
    namespace DesignPatterns\Structural\Flyweight;
    
    /**
     * Class Title
     * @package DesignPatterns\Structural\Flyweight
     */
    class Title implements TitleFlyweightInterface
    {
        /**
         * @var string
         */
        protected $name;
    
        /**
         * Contract constructor.
         *
         * @param string $name
         */
        public function __construct(string $name)
        {
            $this->name = $name;
        }
    
        /**
         * @param string $color
         *
         * @return string
         */
        public function print(string $color): string
        {
            return sprintf('This is %s title with color %s.', $this->name, $color);
        }
    }
    
                  
  • TitleFlyweightInterface.php
                  
    <?php
    
    namespace DesignPatterns\Structural\Flyweight;
    
    /**
     * Interface TitleFlyweightInterface
     * @package DesignPatterns\Structural\Flyweight
     */
    interface TitleFlyweightInterface
    {
        /**
         * @param string $color
         *
         * @return string
         */
        public function print(string $color): string;
    }
    
                  
  • Test case:

    FactoryTest.php
      
    <?php
    
    namespace DesignPatterns\Tests\Structural\Flyweight;
    
    use DesignPatterns\Structural\Flyweight\Factory;
    use PHPUnit_Framework_TestCase;
    
    class FlyweightTest extends PHPUnit_Framework_TestCase
    {
        /**
         * @var Factory
         */
        protected static $factory;
    
        public static function setUpBeforeClass(): void
        {
            self::$factory = new Factory();
        }
    
        public function testCreateFirstTitle()
        {
            $firstTitle = self::$factory->get('first');
            $this->assertInstanceOf('DesignPatterns\Structural\Flyweight\TitleFlyweightInterface', $firstTitle);
        }
    
        public function testCreateSecondTitle()
        {
            $secondTitle = self::$factory->get('second');
            $this->assertInstanceOf('DesignPatterns\Structural\Flyweight\TitleFlyweightInterface', $secondTitle);
        }
    
        public function testSameFirstTitleObjects()
        {
            $firstTitle = self::$factory->get('first');
            $sameFirstTitle = self::$factory->get('first');
            $this->assertSame($firstTitle, $sameFirstTitle);
        }
    
        public function testSameSecondTitleObjects()
        {
            $secondTitle = self::$factory->get('second');
            $sameSecondTitle = self::$factory->get('second');
            $this->assertSame($secondTitle, $sameSecondTitle);
        }
    
        public function testPrint()
        {
            $firstTitle = self::$factory->get('first');
            $this->assertEquals('This is first title with color black.', $firstTitle->print('black'));
        }
    
        public function testFactoryCount()
        {
            $this->assertEquals(2, self::$factory->count());
        }
    }