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());
        }
    }