adapter Адаптер (англ. Adapter) - структурний шаблон проєктування, призначений для організації використання функцій об’єкта, недоступного для модифікації, через спеціально створений інтерфейс.

Дозволяє привести нестандартний або незручний інтерфейс якогось класу до інтерфейсу, сумісного з вашим кодом. Адаптер дозволяє класам працювати разом стандартним чином, що зазвичай не виходить через несумісні інтерфейси, надаючи для цього прошарок із інтерфейсом, зручним для клієнтів, самостійно використовуючи оригінальний інтерфейс.

Ми маємо клас CashBox. CashBox->setCash() приймає тільки об’єкти типу DollarInterface. Уявімо, що у нас є кількох закусочних у різних куточках світу. У кожному з них своя валюта. А наш метод вміє працювати лише з доларами. Плюс для правильного підрахунку необхідно конвертувати валюту. Щоб привести все до одного вигляду, нам і потрібен Адаптер.

  • Dollar
    • DollarInterface.php
                    
      <?php
      
      namespace DesignPatterns\Structural\Adapter\Dollar;
      
      /**
       * Interface DollarInterface
       * @package DesignPatterns\Structural\Adapter\Dollar
       */
      interface DollarInterface
      {
          /**
           * @return float
           */
          public function getCash(): float;
      }
      
                    
    • DollarsCash.php
                    
      <?php
      
      namespace DesignPatterns\Structural\Adapter\Dollar;
      
      /**
       * Class DollarsCash
       * @package DesignPatterns\Structural\Adapter\Dollar
       */
      class DollarsCash implements DollarInterface
      {
          /**
           * @var float
           */
          protected $cash;
      
          /**
           * DollarsCash constructor.
           *
           * @param float $cash
           */
          public function __construct(float $cash)
          {
              $this->cash = $cash;
          }
      
          /**
           * @return float
           */
          public function getCash(): float
          {
              return $this->cash;
          }
      }
      
                    
  • Euro
    • EuroCash.php
                    
      <?php
      
      namespace DesignPatterns\Structural\Adapter\Euro;
      
      /**
       * Class EuroCash
       * @package DesignPatterns\Structural\Adapter\Euro
       */
      class EuroCash implements EuroInterface
      {
          /**
           * @var float
           */
          protected $cash;
      
          /**
           * EuroCash constructor.
           *
           * @param float $cash
           */
          public function __construct(float $cash)
          {
              $this->cash = $cash;
          }
      
          /**
           * @return float
           */
          public function getCash(): float
          {
              return $this->cash;
          }
      }
      
                    
    • EuroInterface.php
                    
      <?php
      
      namespace DesignPatterns\Structural\Adapter\Euro;
      
      /**
       * Interface EuroInterface
       * @package DesignPatterns\Structural\Adapter\Euro
       */
      interface EuroInterface
      {
          /**
           * @return float
           */
          public function getCash(): float;
      }
      
                    
  • CashBox.php
                  
    <?php
    
    namespace DesignPatterns\Structural\Adapter;
    
    use DesignPatterns\Structural\Adapter\Dollar\DollarInterface;
    
    /**
     * Class CashBox
     * @package DesignPatterns\Structural\Adapter
     */
    class CashBox
    {
        /**
         * @var float
         */
        protected $cash;
    
        /**
         * @return float
         */
        public function getSumCashInCashBox()
        {
            return $this->cash;
        }
    
        /**
         * @param DollarInterface $dollarCash
         *
         * @return void
         */
        public function setCash(DollarInterface $dollarCash)
        {
            $this->cash += $dollarCash->getCash();
        }
    }
    
                  
  • EuroAdapter.php
                  
    <?php
    
    namespace DesignPatterns\Structural\Adapter;
    
    use DesignPatterns\Structural\Adapter\Dollar\DollarInterface;
    use DesignPatterns\Structural\Adapter\Euro\EuroInterface;
    
    /**
     * Class EuroAdapter
     * @package DesignPatterns\Structural\Adapter
     */
    class EuroAdapter implements DollarInterface
    {
        const EXCHANGE_RATE = 0.9;
    
        /**
         * @var EuroInterface
         */
        protected $euroCash;
    
        /**
         * EuroAdapter constructor.
         *
         * @param EuroInterface $euroCash
         */
        public function __construct(EuroInterface $euroCash)
        {
            $this->euroCash = $euroCash;
        }
    
        /**
         * @return float
         */
        public function getCash(): float
        {
            return $this->euroCash->getCash() * self::EXCHANGE_RATE;
        }
    }
    
                  
  • Test case:

    AdapterTest.php
      
    <?php
    namespace DesignPatterns\Tests\Structural\Adapter;
    
    use DesignPatterns\Structural\Adapter\CashBox;
    use DesignPatterns\Structural\Adapter\Dollar\DollarsCash;
    use DesignPatterns\Structural\Adapter\Euro\EuroCash;
    use DesignPatterns\Structural\Adapter\EuroAdapter;
    use TypeError;
    
    class AdapterTest extends \PHPUnit_Framework_TestCase
    {
        public function testGetSumWithDollarCash()
        {
            $cashBox = new CashBox();
            $dollarCash = new DollarsCash(15);
    
            $cashBox->setCash($dollarCash);
            $this->assertEquals($cashBox->getSumCashInCashBox(), $dollarCash->getCash());
        }
    
        public function testTypeErrorGetSumWithEuroCash()
        {
            $this->expectException(TypeError::class);
            $cashBox = new CashBox();
            $euroCash = new EuroCash(15);
    
            $cashBox->setCash($euroCash);
        }
    
        public function testAdapterForEuroCash()
        {
            $cashBox = new CashBox();
            $euroCash = new EuroCash(10);
            $dollarCash = new DollarsCash(15);
            $euroCashAdapter = new EuroAdapter($euroCash);
    
            $cashBox->setCash($euroCashAdapter);
            $cashBox->setCash($dollarCash);
            $this->assertEquals($cashBox->getSumCashInCashBox(), $euroCashAdapter->getCash() + $dollarCash->getCash());
        }
    }