Understanding the Adapter Pattern with PHP

The Adapter Pattern is a structural design pattern that allows objects with incompatible interfaces to work together. It acts as a bridge between two incompatible interfaces, making it possible for a class to use the functionality of another class.

In this article, we’ll explore the Adapter Pattern using an example in PHP. We’ll create a scenario where a Person can read both a physical book and an eReader (like Kindle or Nook) using a common interface.

The Concept

Imagine we have a Person class that can read a book. A traditional Book has methods to open and turnPage, while an eReader (like Kindle or Nook) has different methods such as turnOn and pressNext. We want to create an adapter that allows the Person to read both physical books and eReaders seamlessly.

The Implementation

Step 1: Creating the Common Interface

First, we define a BookInterface that both Book and our adapter will implement.

  1. BookInterface.php
namespace App;

interface BookInterface
{
    public function open();
    public function turnPage();
}

Step 2: Implementing the Book Class

Next, we create a Book class that implements the BookInterface.

2. Book.php

namespace App;

class Book implements BookInterface
{
    public function open()
    {
        var_dump('Opening the paper book');
    }

    public function turnPage()
    {
        var_dump('Turning the page of the paper book');
    }
}

Step 3: Creating the eReader Interface and Classes

We define an interface for eReaders and implement it in Kindle and Nook classes.

3. eReaderInterface.php

namespace App;

interface eReaderInterface
{
    public function turnOn();
    public function pressNext();
}

4. Kindle.php

namespace App;

class Kindle implements eReaderInterface
{
    public function turnOn()
    {
        var_dump('Turning the Kindle on');
    }

    public function pressNext()
    {
        var_dump('Pressing the next button to turn the page');
    }
}

5. Nook.php

namespace App;

class Nook implements eReaderInterface
{
    public function turnOn()
    {
        var_dump('Turning the Nook on');
    }

    public function pressNext()
    {
        var_dump('Pressing the next button to turn the page');
    }
}

Step 4: Creating the Adapter

We create an eReaderAdapter class that implements the BookInterface and adapts an eReaderInterface to it.

6. eReaderAdapter.php

namespace App;

class eReaderAdapter implements BookInterface
{
    protected $reader;

    public function __construct(eReaderInterface $reader)
    {
        $this->reader = $reader;
    }

    public function open()
    {
        return $this->reader->turnOn();
    }

    public function turnPage()
    {
        return $this->reader->pressNext();
    }
}

Step 5: Creating the Person Class

Finally, we create a Person class that can read any BookInterface implementation.

7. Index.php

require 'vendor/autoload.php';

use App\Book;
use App\BookInterface;
use App\eReaderAdapter;
use App\Kindle;
use App\Nook;

class Person
{
    public function read(BookInterface $book)
    {
        $book->open();
        $book->turnPage();
    }
}

(new Person())->read(new eReaderAdapter(new Kindle()));
(new Person())->read(new Book());
(new Person())->read(new eReaderAdapter(new Nook()));

When we run this script, it will output the steps for reading both a paper book and an eReader:

Turning the Kindle on
Pressing the next button to turn the page
Opening the paper book
Turning the page of the paper book
Turning the Nook on
Pressing the next button to turn the page

The Adapter Pattern is a powerful way to make two incompatible interfaces compatible. In our example, we used an adapter to allow a Person to read both physical books and eReaders without changing their interfaces.

This approach promotes code reuse and flexibility, allowing your code to work with different types of objects that have similar functionalities but different interfaces.

You can find the complete source code for this example on Gihub

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top