Introduction
In this article I would try to explore a very useful and commonly used design pattern- "The Adapter Pattern". I will cite my examples using C# language.
Background
Adapter pattern is placed under the category of structural design pattern. “Adapter” as the name suggests is the object which lets two mutually incompatible interfaces communicate with each other. But why we want “someone” to adapt to something? You will get an answer if you answer this simple thing- Your laptop charger which you bought in US has flattish pins which easily gets hooked into electrical sockets in US. But when you travel to European countries you may have round holes in the electrical sockets. What do you do then?-Simple buy socket adapters/converters for that.
We use Adapters when incompatible interfaces are involved. Our client object wants to call a method but it is not able to because the interface which our client object can use, is not available with the code which our client object wants to call. Based on what an adapter does the adapter design pattern is also called wrapper pattern, translator pattern. Let’s look at the various participants (objects, interfaces) involved in an adapter pattern.
ITarget: This is the interface which is used by the client to achieve functionality.<o:p>
Adaptee: This is the functionality which the client desires but its interface is not compatible with the client.<o:p>
Client: This is the class which wants to achieve some functionality by using the adaptee’s code.
Adapter: This is the class which would implement ITarget and would call the Adaptee code which the client wants to call.
Using the code
Now let’s look at an example to see how adapter pattern works. Imagine an online shopping portal which displays the products for selling on its home page. These products are coming from a third party vendor with which the portal has tied hands to sell products. The third party vendor already has an inventory system in place which can give the list of products it is selling There is no interface available to online shopping portal with which the portal can call the third party vendor’s inventor code.<o:p>
Since we want to call the third party vendor’s code which is incompatible with client (online shopping portal) code we can apply “Adapter design pattern” here. Let’s first fit in various participants of an adapter pattern in our scenario.<o:p>
ITarget: Method which the online shopping portal calls to get the list of products. Here getting the list of products is the functionality which this portal wants to achieve and this request has been encapsulated in this interface. In short- Functionality to achieve is exposed through this interface.<o:p>
Adaptee: The third party vendor’s code which gives us the list of products.<o:p>
Adapter: The wrapper which would implement ITarget and would call third party vendor’s code.<o:p>
Client: The online shopping portal code which gets the list of products and then displays them.<o:p>
Let’s have a look at the code demonstrating adapter pattern depicting the above scenario then we would revisit the various classes to map them to the adapter pattern participant’s.
interface ITarget
{
List<string> GetProducts();
}
public class VendorAdaptee
{
public List<string> GetListOfProducts()
{
List<string> products = new List<string>();
products.Add("Gaming Consoles");
products.Add("Television");
products.Add("Books");
products.Add("Musical Instruments");
return products;
}
}
class VendorAdapter:ITarget
{
public List<string> GetProducts()
{
VendorAdaptee adaptee = new VendorAdaptee();
return adaptee.GetListOfProducts();
}
}
class ShoppingPortalClient
{
static void Main(string[] args)
{
ITarget adapter = new VendorAdapter();
foreach (string product in adapter.GetProducts())
{
Console.WriteLine(product);
}
Console.ReadLine();
}
}
In the above code the participants are mapped as:
ITarget: interface ITarget
Adapter: class VendorAdapter, implementing the ITarget interface and acting as a wrapper/link between VendorAdaptee and ShoppingPortalClient.
Adaptee: class VendorAdaptee, this is the code which ShoppingPortalClient is interested in calling.
Client: class ShoppingPortalClient, the client wants to call the code of VendorAdptee.
The code above is self-explanatory, the client which has access to the interface ITarget wants to call the method VendorAdaptee.GetListOfProduct() but since VendorAdaptee does not have an ITarget interface there was a need to create an adapter VendorAdapter. The VendorAdapter implements ITarget interface and calls the method of adaptee.
Based on how the adapter calls the adaptee it can be named as Class Adapter i.e. when the adapter uses class inheritance to call the Adaptee code. It is called Object Adapter when it uses the object composition to call the adaptee code. For example the VendorAdapter shown above is an object adapter because it creates an instance of (object composition) VendorAdaptee.
Points of Interest
The Adapter design pattern is easy to implement and ensures calling the existing code which was otherwise difficult because their interfaces being incompatible. It is quiet common when legacy code has to be called.<o:p>
History
Version 1 (16/5/2014)