Computer scienceFundamentalsEssentialsSoftware constructionDesign patternsStructural design patterns

Adapter pattern

5 minutes read

While developing an application, you may encounter some problems with the compatibility of your components. The addition of new code makes it necessary to connect it with other parts of the system with different and incompatible interfaces. To deal with this problem, we use a structural design pattern called the Adapter pattern.

What is an Adapter pattern?

The adapter pattern is a structural design pattern that connects different objects with incompatible interfaces. This pattern consists of a single class whose main purpose is to adapt the interface of one object so that another object can interact with it.

As a real-life example, sometimes you need to use a socket/jack/port on some device, but your cable cannot fit in it. The most common example is different power outlets in different countries. For this problem, you can use an intermediate device (adapter) that will allow you to plug in your cable. The adapter pattern works the same way; by creating a single Adapter class.

Adapter pattern example

Let's imagine that you have an object called an Outlet that needs to process requests from the Power plug. But our outlet is American, whereas the power plug is European. A European plug is incompatible with an American socket and so is a European socket with an American plug. European plugs have rounded prongs whereas American plugs have flat prongs. On top of this, the official American voltage is 110V whereas Europe runs on 220V electricity.

For these reasons, you need to use an adapter if you wish to connect the plugs with different outlets. Let's create an abstract adapter that will help connect plugs with different-shaped prongs and also change the voltage from the outlet to fit the appliances' requirements. So, to process this request, let's use an adapter class that will receive our European plug and connects it to the American outlet.

connecting incompatible power plug with outlet using an adapter

The process of implementing an adapter pattern can be described in this simple algorithm:

  1. We create an adapter compatible through the interface with our existing object.

  2. The interface allows the first object to access adapter methods, and now it can make a request to the second object.

  3. We pass our initial request to the adapter, and the adapter converts it to a suitable format for the second object.

Adapter pattern in pseudocode

Now let's try to represent this pattern in pseudocode. First, we will have to define our objects, starting with a USoutlet class.

class USoutlet is
  constructor of USoutlet...

  method getSocket() is ...

  method fits(powerPlug) is
    if (this.getSocket() == powerPlug.getSocket()) then
      return true
    else
      return false

And now we will define our EUplug class.

class EUplug is
  constructor of EUplug...

  method getSocket() is ...

We also need to create USplug class, to have an example of what objects our USoutlet can connect to:

class USplug is
  constructor of USplug ...

  method getSocket() is ...

Now we create our Adapter class which allows us to use the European power plug with the American power outlet. In it, we will have an instance of our USplug, so that our Adapter can interpret a European power plug as if it were American.

class Adapter extends EUplug is
  private field plug: USplug

  constructor Adapter(plug: USplug) is
    this.plug = plug

  method getSocket() is
    return plug.getSocket()

Adapter pattern implementation

We will implement this pattern in our code when we need to describe our objects and Adapter class. First, we instantiate our objects and try to connect them.

powerPlug = new EUplug()
powerOutlet = new USoutlet()

if (powerOutlet.fits(powerPlug)) then
  ...
else
  print("error")

At this point, we will only get an error. So we use the Adapter class:

plugAdapter = new Adapter(powerPlug)

if (powerOutlet.fits(plugAdapter)) then
  ...
else
  print("error")

Now our classes are compatible, so the code should work. This is just an abstract example of how this pattern can be utilized. Mostly you can use it when you don't want to rewrite large chunks of existing code to connect it to your newly written objects which are incompatible with it. But it can also increase the complexity of code sometimes. So if you're working on a relatively small project, it is better just to rewrite some of the code so that the necessary objects are compatible.

Conclusion

It may be necessary for you to work with adapter patterns on a large and rapidly developing project. It will help you provide connections between existing objects and add ones that are incompatible by default, without rewriting your previous code. But it is still a fairly tricky pattern that can increase the complexity of your code.

21 learners liked this piece of theory. 3 didn't like it. What about you?
Report a typo