2.1. Adapter / Wrapper
2.1.1. Purpose
To translate one interface for a class into a compatible interface. Anadapter allows classes to work together that normally could not becauseof incompatible interfaces by providing its interface to clients whileusing the original interface.
2.1.2. Examples
- DB Client libraries adapter
- using multiple different webservices and adapters normalize data sothat the outcome is the same for all
2.1.3. UML Diagram
2.1.4. Code
You can also find this code on GitHub
BookInterface.php
- <?php
- namespace DesignPatterns\Structural\Adapter;
- interface BookInterface
- {
- public function turnPage();
- public function open();
- public function getPage(): int;
- }
Book.php
- <?php
- namespace DesignPatterns\Structural\Adapter;
- class Book implements BookInterface
- {
- /**
- * @var int
- */
- private $page;
- public function open()
- {
- $this->page = 1;
- }
- public function turnPage()
- {
- $this->page++;
- }
- public function getPage(): int
- {
- return $this->page;
- }
- }
EBookAdapter.php
- <?php
- namespace DesignPatterns\Structural\Adapter;
- /**
- * This is the adapter here. Notice it implements BookInterface,
- * therefore you don't have to change the code of the client which is using a Book
- */
- class EBookAdapter implements BookInterface
- {
- /**
- * @var EBookInterface
- */
- protected $eBook;
- /**
- * @param EBookInterface $eBook
- */
- public function __construct(EBookInterface $eBook)
- {
- $this->eBook = $eBook;
- }
- /**
- * This class makes the proper translation from one interface to another.
- */
- public function open()
- {
- $this->eBook->unlock();
- }
- public function turnPage()
- {
- $this->eBook->pressNext();
- }
- /**
- * notice the adapted behavior here: EBookInterface::getPage() will return two integers, but BookInterface
- * supports only a current page getter, so we adapt the behavior here
- *
- * @return int
- */
- public function getPage(): int
- {
- return $this->eBook->getPage()[0];
- }
- }
EBookInterface.php
- <?php
- namespace DesignPatterns\Structural\Adapter;
- interface EBookInterface
- {
- public function unlock();
- public function pressNext();
- /**
- * returns current page and total number of pages, like [10, 100] is page 10 of 100
- *
- * @return int[]
- */
- public function getPage(): array;
- }
Kindle.php
- <?php
- namespace DesignPatterns\Structural\Adapter;
- /**
- * this is the adapted class. In production code, this could be a class from another package, some vendor code.
- * Notice that it uses another naming scheme and the implementation does something similar but in another way
- */
- class Kindle implements EBookInterface
- {
- /**
- * @var int
- */
- private $page = 1;
- /**
- * @var int
- */
- private $totalPages = 100;
- public function pressNext()
- {
- $this->page++;
- }
- public function unlock()
- {
- }
- /**
- * returns current page and total number of pages, like [10, 100] is page 10 of 100
- *
- * @return int[]
- */
- public function getPage(): array
- {
- return [$this->page, $this->totalPages];
- }
- }
2.1.5. Test
Tests/AdapterTest.php
- <?php
- namespace DesignPatterns\Structural\Adapter\Tests;
- use DesignPatterns\Structural\Adapter\Book;
- use DesignPatterns\Structural\Adapter\EBookAdapter;
- use DesignPatterns\Structural\Adapter\Kindle;
- use PHPUnit\Framework\TestCase;
- class AdapterTest extends TestCase
- {
- public function testCanTurnPageOnBook()
- {
- $book = new Book();
- $book->open();
- $book->turnPage();
- $this->assertEquals(2, $book->getPage());
- }
- public function testCanTurnPageOnKindleLikeInANormalBook()
- {
- $kindle = new Kindle();
- $book = new EBookAdapter($kindle);
- $book->open();
- $book->turnPage();
- $this->assertEquals(2, $book->getPage());
- }
- }