Adapter / Wrapper
Purpose:
To translate one interface for a class into a compatible interface. An adapter allows classes to work together that normally could not because of incompatible interfaces by providing its interface to clients while using the original interface.
BookInterface.php
<?php namespace DesignPatterns\Structural\Adapter; interface BookInterface { public function trunPage(); public function open(); public function getPage(): int; ?>
Book.php
<?php namespace DesignPatterns\Structural\Adapter; class Book implements BookInterface { /** * Varibles Description * * @var int */ private $page; /** * Open the book * * @return Void */ public function open() { $this->page = 1; } /** * Turn pages * * @return Void */ public function turnPage() { $this->page++; } /** * Get total number of pages * * @return Int */ 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 { /** * eBook * * @var EBookInterface */ protected $eBook; /** * Constructor * * @return Void */ public function __construct(EBookInterface $eBook) { $this->eBook = $eBook; } /** * This class makes the proper translation from one interface to another * * @return Void */ public function open() { $this->eBook->unlock(); } /** * This class makes the paper translation from one interface to another * * @return Void */ 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 { /** * Varibles Description * * @var int */ protected $page = 1; /** * Varibles Description * * @var int */ private $totalPages = 100; /** * Function Description * * @return Void */ public function pressNext() { $this->page++; } /** * Function Description * * @return Int */ public function unlock() { } /** * Function Description * * @return array */ public function getPage(): array { return [$this->page, $this->totalPages]; } } ?>
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()); } }