Adapter Pattern — What It Is and How to Use It?
--
Hello Guys, what’s up? I hope you are doing great and having fun! If you are new to this blog series, I request you to also please check out my other blogs on software design patterns! I have yet another cool design pattern to discuss today — The Adapter Pattern. And the good thing is it is quite simple and easy to understand.
What is an Adapter Pattern?
The adapter pattern convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.
The adapter pattern is a structural pattern. It converts the interface of a class into another interface the clients expect. What it means is that, let’s say we have two incompatible components in our system and we want to use them, since we can’t use them directly, we can use the adapter pattern to make them work together. We often end up in such circumstances in our day to day life as a developer. Let me tell you how I ended up using it in my project!
I was working on a project where we had to call an API of an external system in order to calculate tax. The server expected information like zip code, product, price, quantity, etc to calculate the tax. But the bad thing was, it expected the data in XML format. XML and SOAP APIs are really really rare these days except in some banking applications or financial institutions. All our internal APIs expect JSON as input and return JSON as output. Now if we want to make a call to the external server, we have to convert the JSON data into XML format. Let’s see how we can use the adapter pattern to solve this problem.
Step 1 — Define an Adapter interface
This is pretty simple and straightforward. Just define an interface with a method signature in it.
Step 2 — Define an Adaptee
Here since we want to convert the data from JSON to XML, JSON data will be our adaptee. So let’s define a class JSON. This class will contain methods to convert the data from JSON to other formats. For our use case, it contains only one method to convert the data into XML format.
Step 3— Define the concrete adapter class
The final step to implement the adapter pattern is to define the concrete adapter that implements the IDataAdapter interface. It has a reference of an adaptee, using which it calls the method defined in the adaptee to convert the JSON to XML format.
Let’s look at how we can use it
Simple enough right? We wanted to convert our data from one format to another, so we created an adapter interface and a concrete class. And then we used the power of composition to make the conversion. This way we are making two incompatible systems compatible with each other.
But, What is the problem with this? 😕
Now you might be thinking that we could have converted the data by simply calling the convertToXml() method defined in the JSON class.
What’s the point of introducing a new class and then calling its method which internally calls the specific request to convert the data! Aren’t we complicating the solution?
Why are we using it? 😃
Let’s say here we are converting the data from JSON to XML. Now in the future, we may be working with some other data types. Or we may have another requirement to convert the CSV data to JSON or CSV to BSON. At that time client will have to call the specific APIs or methods to convert the data from one format to another. However, we are essentially doing the same thing and that is — Converting the data from one type to another. Hence, it makes more sense to create an adapter interface that defines a common method. The client will only call this common method defined in the interface. Using the power of composition, it will call the specific conversion of the method of a class at the runtime.
Here you can notice that the client is using the adapter reference and just using the same convert() method no matter what the data type is. THAT’S THE BEAUTY OF THE ADAPTER PATTERN❤️.
When To Use It?
- When we are working with two incompatible systems or class or interface, the adapter pattern can be very powerful to use. It makes the code simpler, consistent, and easy to reason about.
- Whenever we have several objects or methods doing something but have different implementations or different syntaxes, an adapter pattern can be definitely a good option! Like in our example, we were only dealing with data conversions. But their algorithms to convert the data into specific types are completely different.
That was it. We have learned the adapter pattern. I hope I explained it in the simplest possible manner and more importantly didn’t confuse you. 😉
Thank you for reading! See you in the next Software Design Pattern. Till then goodbye!