The adapter design pattern is an easy to understand design pattern.You use an adapter pattern to convert the interface of a class into another interface which clients expect.
Example of the adapter interface
For example, let's say you have some code that let's you publish to a WordPress blog. For this example, I'm going to pretend that the current library you use requires you to login, then set the WordPress blog to maintenance mode (which isn't really a thing to do!), then publish the post. It should return the HTML of the blog post.
As it is, originally:
<?php
class BlogPostPublisher
{
public $wp;
public function __construct(WordPressInterface $wp)
{
$this->wp = $wp;
}
public function addBlogPost($title, $post_body)
{
// (This is just a silly example. WordPress doesn't work like this, you can just use the XML-RPC protocol to do it in one request.
$this->wp->login();
$this->wp->setToMaintenanceMode(); // again, not a thing to do in WP but just for this example<br>
$this->wp->post($title, $post_body);
// done!
}
}
interface WordPressInterface
{
public function login();
public function setToMaintenanceMode();
public function post($title, $post_body);
}
class WordPressPublisher implements WordPressInterface
{
private $loginCredentials;
public function login()
{
// login with WP
$this->loginCredentials = SomeWPLibrary::login('user', 'pass');
}
public function setToMaintenanceMode()
{
// now you are logged in, set it to maintenance mode (not really a think in WP!)
SomeWPLibrary::setToMaintenanceMode($this->loginCredentials);
}
public function post($title, $post_body)
{
// and finally send the actual post to the blog
// this should return the HTML of the blog post
return SomeWPLibrary::post($this->loginCredentials, $title, $post_body);
}
}
$poster = new BlogPostPublisher(new WordPressPublisher());
$poster->addBlogPost("Hello, world", "Welcome to my blog post");
But then one day you read about XMLRPC, and you want to update your code base to support this. This doesn't need the login()
, or setToMaintenanceMode()
code. But when posting via XMLRPC, only the post ID is returned, so an additional step is required the get the HTML of the blog post (like the old way did).
This isn't really a good real world example, but hopefully it makes sense and is better than the classic type of example for the adapter extension (things like 'a script to bake a cake', then an adapter to allow a machine to do the same thing).
So, we can use an adapter to use the XMLRPC poster, without having to edit any of the original code.
<?php
class XMLRPCPublisher implements WordPressInterface
{
public function login()
{
// don't do anything here - it isn't needed
}
public function setToMaintenanceMode()
{
// don't do anything here - it isn't needed
}
public function post($title, $post_body)
{
$post_id = XMLRPCLibrary::post('user', 'pass', $title, $post_body);
return XMLRPCLibrary::getHtmlForPost($post_id);
}
}
$poster = new BlogPostPublisher(new XMLRPCPublisher());
$poster->addBlogPost("Hello, world", "Welcome to my blog post");
Benefits of the adapter design pattern
One of the key and main reasons to use this is when your code needs to change its functionality a bit, but you don't want to make any changes to the core base. In the example above, you could pretend that this code supported multiple users and they had the option between selecting uploaders to the (old) WordPress way, maybe a blogger.com interface, and the new WP XML-RPC one. You wouldn't want to have to edit all of the existing code. So create an adapter so you can get the new XML-RPC code working with the existing interfaces.
Design pattern type: Structural design pattern
Comments →The Adapter Design Pattern in PHP