What is Adapter Design Pattern? Adapter Design Pattern is a structural design pattern that can somewhat be compared to real-life problems we face with plugs. Before we roll out the definition, let us think of a real-life example. If you have ever travelled and stopped by a hotel you might have needed an extra adapter to plug your phone’s or laptop’s charger into the hotel’s wall outlet. This especially happens when you travel to a foreign nation. So, what are the adapters? Adapters are connectors that change the plug shape to match the electrical outlet. This is exactly what the adapter design pattern does. The adapter design pattern’s purpose is to lay down criteria that make classes work together that could not otherwise because of incompatible interfaces. The intent is to convert the interface of one class into another interface so that it becomes compatible with what the client expects. The adapter is also known as wrapper. Let us see, what is adapter design pattern?
What is Adapter Design Pattern: A brief explanation
As mentioned earlier, the adapter design pattern falls in the category of structural design patterns. Structural patterns are mainly concerned with the composition of classes and objects. They follow the inheritance principle of object-oriented paradigms. The adapter design pattern makes one interface conform to another, providing a uniform abstraction of different interfaces. So, how do we define – what is adapter design pattern?
Read also: "Decorator design pattern in java with examples"
Putting everything together we have discussed so far – The adapter design pattern proposes a way to convert the interface of a class into another interface, whatever is expected by the client. Adapter Design Interface allows us to design our system in such a way that allows incompatible classes to work together. What is the motivation of object adapter design pattern? Why would we adhere to such a concept?
What is the motivation of object adapter design pattern?
The motivation of object adapter design pattern can be inferred from an example of an editor that allows us to draw shapes that convert into pictures and diagrams. Basically, if we are trying to design such an editor, we need classes that represent geometric shapes. A Line class for a line shape and a polygon class for a polygon shape. And these classes are subclasses of the Shape class that has abstract methods. Since, these “geometric” shapes share something in common, they are easier to implement. However, if we want to add a text shape that can display and edit the text on the go, converting it into a word art kind of a thing, comparatively this is a tedious work. This will involve complicated screen update and buffer management. Now, you will try to use an already built class from a user interface library for displaying and editing such a text.
Read also: "Design Patterns: A quick guide to Observer pattern in Java"
Normally, we would be reusing such a class to implement our version of text shape. The catch here is that the library class is not compatible with our Shape class, it is sort of “unpluggable”! How can we use an existing class that is completely unrelated to our application’s class interfaces? This is where the adapter design pattern comes in handy. What we can do is, we can define text shape class in such a way that it “adapts” the library class’s interface to that of shape class in our application i.e. make it pluggable. And in more general sense attach the adapter to our plug, so that it can work with the existing socket.
As you can see in the class diagram above, the adapter is the class (text shape) that is composed with the target interface, the shape class. The library class can be considered as the adaptee interface. You can think of the client as the application’s entry point that makes request to the adapter by calling a method on it using the target interface.
How is the adapter design pattern used?
-
The adapter is called by the client by calling a method on it using the interface of the target class.
-
The adapters job is to translate the request from the client onto the adaptee using the adaptee’s interface.
-
The client does not know anything about the adapter because they are decoupled.
Read also: "Factory Design Patterns in Java"
Let’s take a look at a simple example of an adapter design pattern in java to better understand what is going on in here.
Adapter Pattern in Java
Suppose that we have a pug (a dog breed) and a tiger and we want our pug to act as if it is a tiger. In real life, you need to train that dog to be fearless. Programmatically we can create a pug adaptor that can implement the tiger class to make it behave in a tiger like way. Let us see an example.
1. First of all, we need the Dog Interface
Fig: Adapter Design Pattern in java – Dog Interface
Our dog interface imposes two Dog characteristics via the bark and run methods.
2. We also need a concrete class that implements Dog.
Fig: Adapter Design Pattern in java – Pug class
The bark and run methods have extended definition in the Pug concrete class.
3. Similarly, we need a Tiger interface
Fig: Adapter Design Pattern in java – Tiger interface
4. And we will need a concrete class that implements the tiger interface.
Fig: Adapter Design Pattern in java – White Tiger Class
5. Now, we need the adapter, the Dog Adapter
Fig: Adapter Design Pattern in java – Adapter
The Dog Adapter declares a constructor that takes Dog type of object. It extends the Tiger interface and by overriding the methods from the tiger interface, we are making the dog run and roar. In other words, the adapter class has translated the request on the adaptee using the adaptee interface. Dog interface is the adaptee interface.
6. Finally, let’s test our Pug
Fig: Adapter Design Pattern in java – Testing the design pattern
In this step, we have created the pug (dog) object, and a tiger object. We have also wrapped the pug in a dog adapter which makes it behave like a tiger. The pug in its normal form can bark and run like a dog. The white tiger object can also do the same. However, now inside the adapter is calling the adaptee method from its reference.
Read also: "Singleton Design Pattern – A thoughtful dive into Object Structures and Creation"
So, how does this all relate? As per the definition of adapter design pattern, we know that the Adapter Pattern converts the interface of a class into another interface the clients expect. By the do not think of an interface as the “interface in java”, it has been used to refer in a more general sense structure of the class. In our case think of compatibility. What we have done here is the same thing, we took a dog class and using java’s interface pattern tried to match it with the tiger interface by calling the dog methods inside of the extended method definitions of the Tiger class.
When should we use the adapter design pattern?
-
When we want to use an existing class, but its interface does not match with the one we need.
-
When we ourselves want to create a reusable class that works with unrelated classes that do not necessarily have compatible interfaces.
On an ending note we would like to say that the motivation of object adapter design pattern mainly comes from the ET++ drawing application. It uses the TextShape adapter class for text editing, a problem we discussed in the “what is the motivation of object adapter design pattern” section. If you have come this far in this article, this example is a treat for you.