Adapter Pattern: The right way

Follow the series topic regarding to Design Patterns Overview, today we will dive in to Adapter Pattern to understand clearly about this really useful pattern. If you want to know more other patterns, Let’s checkout the series of Design patterns

Adapter Pattern’s definition

According to Wikipedia document:

In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used from another interface.[1] It is often used to make existing classes work with others without modifying their source code.

In visualization:
Adapter pattern

When we use?

As the definition, we will use Adapter Pattern to make existing classes work with others without modifying the source doe. But this seems not really clear. Let’s see this scenario.

class FacebookNotification {
  public function __construct() {
    /* Your constructor implementation */
  }
 
  public function sendNotification($message) {
    /* Send Facebook notification message */
    echo $message;
  }
}
$facebookNotification = new FacebookNotification();
$facebookNotification->sendNotification('You have a new message');

In the code above, we can see that we are utilizing a Facebook class to simply send a message. We directly create the object of the FacebookNotification class and call the method sendNotification via Facebook. You may used this code in multiple places in your application.

In one day, Facebook changes the API method name from sendNotification to an other e.g: sendMessage. Then this clearly impact to your application because you have been using the sendNotification method. We have to change all sendNotification to sendMessage, then test again every where that use this method, but this kind of pain may happen again.

What is the solution?

Adapter pattern is the answer for this situation, we should create a wrapper interface that handle this problem. We will not make any change in the external class library because we do not have control over it then it my change any time.

Let’s see the code that shows the Adapter pattern in action:

class FacebookNotification {
  public function __construct() {
    /* Your constructor implementation */
  }
 
  public function sendNotification($message) {
    /* Send Facebook notification message */
    echo $message;
  }
}
 
/**
 * Create a simple Interface for each Adapter we create
 */
interface notificationAdapter {
  public function buzz($message);
}
 
class FacebookAdapter implements notificationAdapter {
  private $facebook;
 
  public function __construct(FacebookNotification $facebook) {
    $this->facebook = $facebook;
  }
 
  public function buzz($message) {
    $this->facebook->sendNotification($message);
  }
}

Let’s review the code above then you will see that we have not made any change into the FacebookNotification class. Instead we have created an interface for our notification adapter and one adapter class for Facebook.

Then we have made the object of the adapter class instead of the main FacebookNotification class. While creating an object of adapter class we will parse the object of the main FacebookNotification class as an argument, by implementing this way the adapter class has a reference to the main class and it can call the required methods of the main FacebookNotification class.

This is how we utilize this method:

/* We call the method this way */
$facebookNotification = new FacebookAdapter(new FacebookNotification());
$facebookNotification->buzz('Adapter pattern is awesome');

Now if one day Facebook changes its method name from sendNotification to pingMessage for example, then we only have to make changes in FacebookAdapter. Let’s take a look at the adapter code to adapt the changes, just one place and nothing more.

class FacebookAdapter implements notificationAdapter {
  private $facebook;
 
  public function __construct(FacebookNotification $facebook) {
    $this->facebook = $facebook;
  }
 
  public function buzz($message) {
    $this->facebook->pingMessage($message);
  }
}

What if we need to add new Adapter?

Now, we already understand clearly about the adapter pattern that why we can very easy to add new class dependent on the existing adapter. Let’s say we have the Twitter API in this moment.

Then instead of using the Twitter class directly, we should use the same adapter pattern we have used for Facebook

class TwitterNotification {
  public function __constructor() {
    /* constructor implementation if needed */
  }
 
  public function twitterBuzz($message) {
    echo $message;
  }
}
 
class TwitterAdapter implements notificationAdapter {
  private $twitter;
 
  public function __construct(TwitterNotification $twitter) {
    $this->twitter = $twitter;
  }
 
  public function buzz($message) {
    $this->twitter->twitterBuzz($message);
  }
}
 
/* Call the method */
$twitterNotification = new TwitterAdapter(new TwitterNotification());
$twitterNotification->buzz('Adapter pattern is amazing');

As you see, the code is better now. We define the method that is available to third-party then if they change their API, we simply change the dependent class without change the external interface, don’t have to change in many places that we call the API.

Conclusion

Adapters are extremely useful and help developers to write cleaner and more maintainable code. We hope that you will apply this pattern in the right way. If you have any additional comments or questions, please don’t hesitate to leave a comment below.

Other design patterns:

Related Post

Leave a Reply