Adapter Pattern

Introduction and Implementation of Adapter Pattern


Category: Design Patterns Tags: C#


Introduction

        Adapter Pattern is Structural Design Pattern which is used when we have to use functionality of an interface which is incompatible to client. As it name suggests, it creates an adapter which adepts incompatible interface to be used as another interface. Simply in Adapter Pattern two incompatible interfaces work together. Structural Patterns are design patterns which ease the design and using that large structures can be build.

Implementation

        Suppose HP Computers has an online portal where they display their products, for that they have Product class implemented:

interface IProduct
{
List<Product> GetAllProductList();
}

class Product : IProduct
{
public string ProductName;
public string ProductSerial;

public Product()
{ }

public Product(string name, string serial)
{
ProductName = name;
ProductSerial = serial;
}

/// <summary>
/// Returns list of hp products
/// </summary>
/// <returns></returns>
public virtual List<Product> GetAllProductList()
{
List<Product> products = new List<Product>()
{
new Product("hp-i3", "123-456"),
new Product("hp-i5", "456-789")
};

return products;
}
}

Product class has two properties for Name and Serial Number and a virtual method which returns list of products by HP. The other class called HPComputers which is compatible with Interface IProduct:

/// <summary>
/// Client
/// </summary>
class HPComputers
{
IProduct _product;

/// <summary>
/// Dependency Injuction
/// </summary>
/// <param name="product">Interface of Product class</param>
public HPComputers(IProduct product)
{
this._product = product;
}

/// <summary>
/// Displays all products list
/// </summary>
public void DisplayProducts()
{
var products = _product.GetAllProductList();
foreach (Product p in products)
{
Console.WriteLine("Product Name: {0} Product SrNo: {1}", p.ProductName, p.ProductSerial);
}
}
}

Above class is dependent on IProducts (Product class's interface is injected) and having method to display all products. Suppose other company Dell just affiliated with HP and wants to show its products on HP’s portal for that they have one class which provides list of their products:

class DellProduct
{
//2d array of product name ans serial number
string[,] products = new string[,] { { "Dell-1", "d123" }, { "Dell-2", "d456" } };

//Property
public string[,] Products
{
get { return products; }
}
}

Now above class has Dell’s products list and we have to consume it to show dell’s product along HP’s. But HPComputers class which displays products and compatible with only IProducts, we don’t want to make any changes to this class. So here we have to create an adapter between these two (IProduct and DellProduct):

class Adapter : Product
{
DellProduct _productDell;

/// <summary>
/// Injecting DellProduct class which was uncompatible
/// </summary>
/// <param name="productDell"></param>
public Adapter(DellProduct productDell)
{
this._productDell = productDell;
}

/// <summary>
/// Overriding this method to combine hp and dell products
/// </summary>
/// <returns></returns>
public override List<Product> GetAllProductList()
{
//using base to get hp products first into product list object
List<Product> products = base.GetAllProductList();

string[,] productsDell = _productDell.Products;

//adding dell products to product list
for (int i = 0; i < productsDell.GetLength(0); i++)
{
products.Add(new Product(productsDell[i, 0], productsDell[i, 1]));
}

return products;
}
}

Above class is inherited from Product class of course it has to be compatible with HPComputers (which accepts only IProduct). We create object of DellProducts and override method which provides list of products. First we load HP products in list then we have to append dell’s products as well.So now we are done with adapter, adapter’s base class is Products so it can be passed to HPComputers and here we can see:

 

HPComputers class => Client

DellProduct class => Adaptee

IProduct interface => Target

Adapter class => Adapter

 

Now let’s execute the code from Main method:

 

DellProduct adapteeDellProduct = new DellProduct();
//creating reference of IProduct using Adapter object
IProduct targerInterfaceProduct = new Adapter.Adapter(adapteeDellProduct);
//HPComputers takes only IProducts but we manipulated it using upcasting of Adapter class
HPComputers hpComputers = new HPComputers(targerInterfaceProduct);

hpComputers.DisplayProducts();

We will have output which will display both HP and Dell products:

 

Product Name: hp-i3 Product SrNo: 123-456

Product Name: hp-i5 Product SrNo: 456-789

Product Name: Dell-1 Product SrNo: d123

Product Name: Dell-2 Product SrNo: d456

 

So, this was Adapter pattern which is really useful when we cannot change code of a class but need to use functionality of an incompatible interface in that class.


Like 1 Person
Last modified on 1 September 2018
Nikhil Joshi

Nikhil Joshi
Ceo & Founder at Dotnetlovers
Atricles: 126
Questions: 9
Given Best Solutions: 8 *

Comments:

No Comments Yet

You are not loggedin, please login or signup to add comments:

Existing User

Login via:

New User



x