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

Alt Adapter UML Diagram

2.1.4. Code

You can also find this code on GitHub

BookInterface.php

  1. <?php
  2.  
  3. namespace DesignPatterns\Structural\Adapter;
  4.  
  5. interface BookInterface
  6. {
  7. public function turnPage();
  8.  
  9. public function open();
  10.  
  11. public function getPage(): int;
  12. }

Book.php

  1. <?php
  2.  
  3. namespace DesignPatterns\Structural\Adapter;
  4.  
  5. class Book implements BookInterface
  6. {
  7. /**
  8. * @var int
  9. */
  10. private $page;
  11.  
  12. public function open()
  13. {
  14. $this->page = 1;
  15. }
  16.  
  17. public function turnPage()
  18. {
  19. $this->page++;
  20. }
  21.  
  22. public function getPage(): int
  23. {
  24. return $this->page;
  25. }
  26. }

EBookAdapter.php

  1. <?php
  2.  
  3. namespace DesignPatterns\Structural\Adapter;
  4.  
  5. /**
  6. * This is the adapter here. Notice it implements BookInterface,
  7. * therefore you don't have to change the code of the client which is using a Book
  8. */
  9. class EBookAdapter implements BookInterface
  10. {
  11. /**
  12. * @var EBookInterface
  13. */
  14. protected $eBook;
  15.  
  16. /**
  17. * @param EBookInterface $eBook
  18. */
  19. public function __construct(EBookInterface $eBook)
  20. {
  21. $this->eBook = $eBook;
  22. }
  23.  
  24. /**
  25. * This class makes the proper translation from one interface to another.
  26. */
  27. public function open()
  28. {
  29. $this->eBook->unlock();
  30. }
  31.  
  32. public function turnPage()
  33. {
  34. $this->eBook->pressNext();
  35. }
  36.  
  37. /**
  38. * notice the adapted behavior here: EBookInterface::getPage() will return two integers, but BookInterface
  39. * supports only a current page getter, so we adapt the behavior here
  40. *
  41. * @return int
  42. */
  43. public function getPage(): int
  44. {
  45. return $this->eBook->getPage()[0];
  46. }
  47. }

EBookInterface.php

  1. <?php
  2.  
  3. namespace DesignPatterns\Structural\Adapter;
  4.  
  5. interface EBookInterface
  6. {
  7. public function unlock();
  8.  
  9. public function pressNext();
  10.  
  11. /**
  12. * returns current page and total number of pages, like [10, 100] is page 10 of 100
  13. *
  14. * @return int[]
  15. */
  16. public function getPage(): array;
  17. }

Kindle.php

  1. <?php
  2.  
  3. namespace DesignPatterns\Structural\Adapter;
  4.  
  5. /**
  6. * this is the adapted class. In production code, this could be a class from another package, some vendor code.
  7. * Notice that it uses another naming scheme and the implementation does something similar but in another way
  8. */
  9. class Kindle implements EBookInterface
  10. {
  11. /**
  12. * @var int
  13. */
  14. private $page = 1;
  15.  
  16. /**
  17. * @var int
  18. */
  19. private $totalPages = 100;
  20.  
  21. public function pressNext()
  22. {
  23. $this->page++;
  24. }
  25.  
  26. public function unlock()
  27. {
  28. }
  29.  
  30. /**
  31. * returns current page and total number of pages, like [10, 100] is page 10 of 100
  32. *
  33. * @return int[]
  34. */
  35. public function getPage(): array
  36. {
  37. return [$this->page, $this->totalPages];
  38. }
  39. }

2.1.5. Test

Tests/AdapterTest.php

  1. <?php
  2.  
  3. namespace DesignPatterns\Structural\Adapter\Tests;
  4.  
  5. use DesignPatterns\Structural\Adapter\Book;
  6. use DesignPatterns\Structural\Adapter\EBookAdapter;
  7. use DesignPatterns\Structural\Adapter\Kindle;
  8. use PHPUnit\Framework\TestCase;
  9.  
  10. class AdapterTest extends TestCase
  11. {
  12. public function testCanTurnPageOnBook()
  13. {
  14. $book = new Book();
  15. $book->open();
  16. $book->turnPage();
  17.  
  18. $this->assertEquals(2, $book->getPage());
  19. }
  20.  
  21. public function testCanTurnPageOnKindleLikeInANormalBook()
  22. {
  23. $kindle = new Kindle();
  24. $book = new EBookAdapter($kindle);
  25.  
  26. $book->open();
  27. $book->turnPage();
  28.  
  29. $this->assertEquals(2, $book->getPage());
  30. }
  31. }