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.
- 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