In my last post, I discussed one of the creational design patterns now will discuss the adapter design pattern which is a structural design pattern.
Before moving further if you would like to understand the basic concept and type of design pattern refer to my previous post on Singleton Design Pattern in which I discuss basic concept and type of design pattern very high level. So that will help you to get a better understanding of the adapter design pattern.
As per the gang of four definition adapter design pattern “Match interfaces of different classes”
In software engineering adapter pattern allows the incompatible class to interact with the existing class by converting the interface of one class into an interface expected by the client. Adapter pattern help to reuse the existing functionality as it is a bridge between two incompatible interfaces.
Adapters coverts the interface of one class into an interface a client expects
Let’s take a real-life example, Travelling internationally with electronic devices has become so common and the power plug and socket standard are different in different countries so you need an adapter to convert the shape of your home power plugs to the shape of the outlets in the region of the world you are traveling to.
Now let’s take one technical example, your current application work with XML data and now you are going to plug in some external APIs to your application but that external APIs work with JSON data only. In this situation, you can either rewrite your code to support JSON data or you can ask third-party APIs providers to change their code to support XML. The first option required lots of effort and regression testing as you are going to change your existing code and the second option might be not possible as they are not supporting XML data.
To solve this problem you can create an adapter interface that is responsible to convert one type of object to an incompatible type of object. In our scenario, we can create XML to JSON adapter which will convert XML data to JSON data, and then it will pass to third-party APIs. It is also possible to create a two-way adaptor that converts the call in both directions. following diagram shows how we can implement XML to JSON adapter in our example
Let’s take one more example in which we will going to implement the actual code and using that code we will try to understand the adapter design pattern. you can find same code from Github: Adapter Design Pattern Example
Scenario: We have a product display service that can be display product from two different sources one using file and another by calling the vendor API
So, for the above scenario, we are going to create an IProductSourceAdapter
Interface which has Task<IEnumerable<Product>> GetProducts();
So, the client will use this method to get the list of products.
Also, we are going to implement two different classes. One class for file FileSource
which get the product from a file using GetProductFromFile
method and another for API VendorApiSource
which get products by calling Vendor API under GetProducts
method
Now, we are going to implement FileSourceAdapter
which create an instance of FileSource
and delegate the call to FileSource.GetProductFromFile(_filePath)
In the same way, we are going to implement VendorSourceAdapter
which create an instance of VendorApiSource
and delegate the call to VendorApiSource.GetProducts(_clientApiUrl)
Now, here our client ProductDisplayService
inject IProductSourceAdapter
we don’t care about which particular implementation it is. we will get this information based on the type that gets injected.
- Step 1: Client which has existing business logic.
- Step 2: Client Interface describes a protocol that other classes must follow to be able to collaborate with the client code.
- Step 3: Service has its own logic. The client can’t use this class directly because it has an incompatible interface.
- Step 4: Adapter is receiving a call from the client via client interface and translate calls to the service class
Adapter design pattern follows Single responsibility principle as each service has its own logic and only responsible for one thing like FileSource
getting a product from a file only. Adapter design pattern also follows the Open-Closed principle as you can bring a new type of source without breaking the existing client code.
Also, you can find source code which demonstrate above example from following github link
https://github.com/nibro7778/adapter-design-pattern
Hope you’ll like it!