2.1. Adapter / Wrapper

2.1.1. 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 it’s interface to clients while using the original interface.

2.1.2. Examples

  • DB Client libraries adapter
  • using multiple different webservices and adapters normalize data so that the outcome is the same for all

2.1.3. UML Diagram

Alt Adapter UML Diagram

2.1.4. Code

You can also find these code on GitHub

PaperBookInterface.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

namespace DesignPatterns\Structural\Adapter;

/**
 * PaperBookInterface is a contract for a book
 */
interface PaperBookInterface
{
    /**
     * method to turn pages
     *
     * @return mixed
     */
    public function turnPage();

    /**
     * method to open the book
     *
     * @return mixed
     */
    public function open();
}

Book.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

namespace DesignPatterns\Structural\Adapter;

/**
 * Book is a concrete and standard paper book
 */
class Book implements PaperBookInterface
{
    /**
     * {@inheritdoc}
     */
    public function open()
    {
    }

    /**
     * {@inheritdoc}
     */
    public function turnPage()
    {
    }
}

EBookAdapter.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php

namespace DesignPatterns\Structural\Adapter;

/**
 * EBookAdapter is an adapter to fit an e-book like a paper book
 *
 * This is the adapter here. Notice it implements PaperBookInterface,
 * therefore you don't have to change the code of the client which using paper book.
 */
class EBookAdapter implements PaperBookInterface
{
    /**
     * @var EBookInterface
     */
    protected $eBook;

    /**
     * Notice the constructor, it "wraps" an electronic book
     *
     * @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->pressStart();
    }

    /**
     * turns pages
     */
    public function turnPage()
    {
        $this->eBook->pressNext();
    }
}

EBookInterface.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

namespace DesignPatterns\Structural\Adapter;

/**
 * EBookInterface is a contract for an electronic book
 */
interface EBookInterface
{
    /**
     * go to next page
     *
     * @return mixed
     */
    public function pressNext();

    /**
     * start the book
     *
     * @return mixed
     */
    public function pressStart();
}

Kindle.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

namespace DesignPatterns\Structural\Adapter;

/**
 * Kindle is a concrete electronic book
 */
class Kindle implements EBookInterface
{
    /**
     * {@inheritdoc}
     */
    public function pressNext()
    {
    }

    /**
     * {@inheritdoc}
     */
    public function pressStart()
    {
    }
}

2.1.5. Test

Tests/AdapterTest.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php

namespace DesignPatterns\Structural\Adapter\Tests;

use DesignPatterns\Structural\Adapter\EBookAdapter;
use DesignPatterns\Structural\Adapter\Kindle;
use DesignPatterns\Structural\Adapter\PaperBookInterface;
use DesignPatterns\Structural\Adapter\Book;

/**
 * AdapterTest shows the use of an adapted e-book that behave like a book
 * You don't have to change the code of your client
 */
class AdapterTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @return array
     */
    public function getBook()
    {
        return array(
            array(new Book()),
            // we build a "wrapped" electronic book in the adapter
            array(new EBookAdapter(new Kindle()))
        );
    }

    /**
     * This client only knows paper book but surprise, surprise, the second book
     * is in fact an electronic book, but both work the same way
     *
     * @param PaperBookInterface $book
     *
     * @dataProvider getBook
     */
    public function testIAmAnOldClient(PaperBookInterface $book)
    {
        $book->open();
        $book->turnPage();
    }
}