Click here to Skip to main content
15,895,812 members
Articles / Programming Languages / C#

Understanding and Implementing the Adapter Pattern Using C#

Rate me:
Please Sign up or sign in to vote.
4.78/5 (37 votes)
8 Mar 2012CPOL4 min read 81.7K   1.4K   59  
Understanding when we could find the Adapter pattern useful and how can we have a rudimentary implementation of the Adapter pattern using C#.
This is an old version of the currently published article.

Introduction

This article aims at understanding when we could find the Adapter pattern useful and how can we have a rudimentary implementation of the Adapter pattern using C#.

Background

It was almost 6 years back, at the very beginning of my career, that one of my clients told me to write an adapter. Back then I was unaware of the "Adapter Pattern" but I took his words literally and started my work. I did the required task and wrote an adapter. I think this pattern is something that anyone will find very easy to understand and even implement.

What exactly is an adapter? If I have a source providing me something in some format and my target is expecting that stuff in some other format, then I can hook in a module in between these two guys that will do the conversion. This entity working in between these two is my adapter. I remember the adapter that I used to power up my 16 bit gaming console (expecting 9 volts of power) using a 220 volt power supply.

Adapter pattern article image

The Adapter we are going to talk about here is also on the same lines but it works for classes and objects. If I have a class that is exposing some functions but my client is expecting some other interface, then I can have an adapter in between. The benefit of having an adapter is that the client need not be changed every time I choose to change my underlying object that is being used. I just have to have an adapter written for the new target and the client code will work seamlessly.

Using the Code

GoF defines Adapter pattern as "Convert the interface of a class into another interface that the clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces."

Adapter pattern article image

Let us try to understand this class diagram:

  • Target: Defines the interface that the client uses.
  • Adapter: It uses (adapts) the Adaptee's interface and exposes the Target interface to the client.
  • Adaptee: This is the object whose interface needs to be adapted.
  • Client: It uses the Adaptee functionality via the adapter interface, i.e., Target.

One good example of when we could find this pattern useful is when visualizing an MP3 player application. This MP3 player application was developed on top of some library (say DirectX). The application makes DirectX specific calls to achieve the playback functionality. After some time, there is a requirement of using XNA for playback instead of DirectX. This could mean either rewriting the complete application to change the DirectX specific calls to XNA specific calls, or we could simply write an adapter for XNA in such a way that the client application could work with minimum or no changes.

Let us try to write a small toy application to demonstrate this concept. We will create a small client that will use two libraries (dummy) to perform some operations. These two libraries expose different interfaces so we will write a small adapter to use the libraries. Let us look at the two libraries first, Adaptee:

C#
//Library One
class LibraryOne
{
    public void ThisIsHowOneDoesIt()
    {
        Console.Write("Using Library ONE to perform the action\n");
    }
}

//Library Two
class LibraryTwo
{
    public string ThisIsHowTwoDoesIt()
    {
        return "Using Library TWO to perform the action";
    }
}

Now let us write the adapter interface for our concrete adapters, i.e., Target from the above class diagram.

C#
interface IAdapter
{
    void Do();        
}

and now we will write the concrete Adapter classes to use the two libraries:

C#
//Adapter for first library
class AdapterOne : IAdapter 
{
    private LibraryOne one = null;

    public AdapterOne()
    {
        one = new LibraryOne();
    }

    #region IAdapter Members

    public void Do()
    {
        one.ThisIsHowOneDoesIt();
    }

    #endregion
}
//Adapter for second library
class AdapterTwo : IAdapter 
{
    private LibraryTwo two = null;

    public AdapterTwo()
    {
        two = new LibraryTwo();
    }

    #region IAdapter Members

    public void Do()
    {
        Console.WriteLine(two.ThisIsHowTwoDoesIt() + "\n"); ;
    }

    #endregion
}

So now we have a single interface that the client can use. The respective adapters will take care of making the calls to the respective underlying objects. Let us see how the Client can use this adapter.

C#
static void Main(string[] args)
{
    IAdapter adapter = null;

    //Let emulate the decision where the choice of using the underlying system is made
    Console.WriteLine("Enter which library you wanna use to do operation {1,2}");
    int x = Console.Read();

    if (x == '1')
    {
        //Let us choose to use Library one to do something
        adapter = new AdapterOne();
    }
    else if (x == '2')
    {
        //Let us choose to use Library two to do something
        adapter = new AdapterTwo();
    }

    //Just do the operation now
    adapter.Do();
}

So now the client can use the same interface to perform operations using both underlying objects. The Adapter pattern is particularly useful when we have two classes that perform similar functions but have different interfaces. The client wants to use both classes, so instead of having conditional code scattered all around the client code, it would be better and simpler to understand if these two classes share the same interface. We cannot change the class interfaces, but we can have an Adapter which allows the client to use a common interface to access the underlying classes.

Before wrapping up, let us look at the class diagram of our small application and compare it with the GoF diagram.

Adapter pattern article image

Points of Interest

This article was written from a beginner's point of view and demonstrated the implementation of the Adapter pattern using a non-realistic example. The Adapter pattern is a really simple but important Design Pattern. The .NET Framework uses this pattern in its core to use the legacy COM component.

History

  • 06 March 2012: First version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
India India

I Started my Programming career with C++. Later got a chance to develop Windows Form applications using C#. Currently using C#, ASP.NET & ASP.NET MVC to create Information Systems, e-commerce/e-governance Portals and Data driven websites.

My interests involves Programming, Website development and Learning/Teaching subjects related to Computer Science/Information Systems. IMO, C# is the best programming language and I love working with C# and other Microsoft Technologies.

  • Microsoft Certified Technology Specialist (MCTS): Web Applications Development with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Accessing Data with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Windows Communication Foundation Development with Microsoft .NET Framework 4

If you like my articles, please visit my website for more: www.rahulrajatsingh.com[^]

  • Microsoft MVP 2015

Comments and Discussions

Discussions on this specific version of this article. Add your comments on how to improve this article here. These comments will not be visible on the final published version of this article.