Адаптер (англ. 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 ());
}
}