This time I’m writing about adapter pattern. This is an easy one to understand. Why? Because our world is full of real-life adapters. The authors of the book gives just this simple example about AC power adapter. We use it while traveling from Europe to United States because we want our laptops work there. So, we take our laptop’s plug-in connect it with an adapter and then plug it into US type wall outlet.
Book example
Code example in the book is quite unreal. Let’s go back to ducks’ example! It’s a little bit far-fetched example but perfectly shows what adapter pattern does for us. We’ve got simplified version of Duck interfaces and classes:
# interface Duck { public function quack(); public function fly(); }
# class MallardDuck implements Duck { public function quack() { echo "Quack! Quack! \n"; } public function fly() { echo "I'm flying!\n"; } }
Those two structures are similar to the one mentioned in the first chapter in the book when strategy pattern was presented to us. But here is something fresh in our application:
# interface Turkey { public function gobble(); public function fly(); }
# class WildTurkey implements Turkey { public function gobble() { echo "Gobble, gobble, gobble...\n"; } public function fly() { echo "I'm flying a short distance.\n"; } }
Because of some strange reasons we can’t use Duck
sub-classes anymore but we are allowed to use Turkey
sub-classes instead. But instances of one and another class have different interfaces and to make it easy and possible to do we’re going to write an adapter class:
# class TurkeyAdapter implements Duck { private $turkey; public function __construct( Turkey $turkey ) { $this->turkey = $turkey; } public function quack() { $this->turkey->gobble(); } public function fly() { for( $i = 5; $i > 0; $i-- ) { $this->turkey->fly(); } } }
Now, we can use Turkey
with Duck
interface:
# $wildTurkey = new WildTurkey(); $turkeyAdapter = new TurkeyAdapter( $wildTurkey ); $turkeyAdapter->quack(); $turkeyAdapter->fly();
After this a little bit unrealistic example authors of the book goes back to the AC power adapter example and explain us how a client use adapter pattern:
- The client makes a request to the adapter by calling a method on on it using the target interface.
- The adapter translates the request into one or more calls on the adaptee using the adaptee interface.
- The client receives the results of the call and never knows there is an adapter doing the translation.
Finally, we get to adapter pattern‘s definition:
The Adapter Pattern converts the interface of a class into another interface the client expects. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.
The adapter’s introduction part in the chapter ends with short explanation about second type of adapters: class adapters. The solutions presented above were object adapter solutions. In programming languages where multiple inheritance is available you can create class adapter instead of object adapter. The only difference is that we use multiple inheritance instead of composition to translate one interface to another.
Then we have a really nice real java-life example There were enumerators in some old Java version and they were replaced with iterators. The Enumeration
interface looked like:
# interface Enumeration { public function hasMoreElements(); public function nextElement(); }
when Iterator
:
# interface JavaIterator { public function hasNext(); public function next(); public function remove(); }
What if you face legacy code that exposes the Enumeration
interface, yet you’d like for your new code to use only iterators. You need to create an adapter!
# class EnumerationIterator implements JavaIterator { private $enumeration; public function __construct( Enumeration $enumeration ) { $this->enumeration = $enumeration; } public function hasNext() { return $this->enumeration->hasMoreElements(); } public function next() { return $this->enumeration->nextElement(); } public function remove() { throw new UnsupportedOperationException( "remove() operation is not supported" ); } }
So, the answer for any legacy code that exposes an interface you’d like to replace with a better version is adapter pattern
The code example above as always can be downloaded from here. Notice that my PHP version of Iterator
class was named JavaIterator
that’s because I didn’t want to conflict with PHP built-in iterator interface.
Other examples
The examples in the book was quite unreal or strictly connected to Java world. But Google is your friend and there are lots of nice PHP examples. I found two twitter services examples on the first page of Google results presented to me. The first post has very nice introduction to adapter pattern. The second is just a nice example with using an adapter to translate more than one interface into target one. I also found that the lady with similar idea of mine wrote more about design patterns and you can find there the post about adapter pattern. She just stopped tagging them with “Head First Design Patterns” tag
Update (2014-04-09)
Today I read an article about interesting library called Flysystem. Once you visit the repository page on Github you’ll notice it’s nothing else as a group of adapters to different file systems. Pretty simple but very useful library. I encourage you to give it some time, read the article and play with the Flysystem itself
Other design patterns
Here is the list of described by me design patterns: