Quick Start On Adaptor Design Pattern

Background

One of the most  frequently used Structural patterns is the Adaptor Design pattern. This pattern simplifies the incompatible interfaces and acts as a bridge between two incompatible interfaces to communicate independently. If you have looked at the SOLIDs principle, the Adaptor design pattern adheres with the Single Responsibility Principle and Open-Closed Principle. For more on the SOLID Principles, please go through this link - Deep Dive Into SOLID Principles.

Real-world Analogy

Let’s put technical terminology aside and understand the common term.

If you look around the real world, there are a lot of examples that will help you learn about Adaptor Pattern.

  1. Your Memory card reader acts as a bridge between the SD card and PC/Laptop to simplify the incompatible interface.
  2. Your mobile charger that converts the power supply from 220V AC to 5V DC
  3. A universal travel adaptor that makes a bridge to convert the incompatible interface from European to Indian socket.
  4. The media player that can play a music file of the format of .mp3, .aac, and many more. These formats are internally converted to one unique format to play the music.
  5. The latest and slimmer laptop has the USB to Ethernet converter to connect the LAN.
  6. Your unused Hard Drive can be using the Hard Drive encloser case and connected via a USB port.
  7. Converting the data in XML format to JSON format to make comparability with other systems.

And many more. If something unique, please do post it in a comment box.

Quick start on Adaptor Design Pattern

Example with Illustration

Let’s consider a very common example that we all know about travel adaptors. The adaptor below will help us convert from Indian type pin to European type pin to accommodate the independent interface.

Quick start on Adaptor Design Pattern

When can we use the Adaptor design pattern?

  • Both the interfaces are different to communicate with each other and independent.
  • An interface builds comparability with existing objects.

Pros

  • The primary business logic can be easily separated from data conversion and hence falls in the Single Responsibility Principle.
  • You can create an N number of types of Adaptors without breaking the client code with the client interface and hence falls in the Open-Closed Principle.
  • Encapsulates code for the conversion part.

Cons

  • The complexity of the code might increase when the need to introduce a new set of interfaces.

UML Representation

Quick start on Adaptor Design Pattern

Code example

Let’s create a converter that converts data from XML format to JSON format by using an Adaptor design pattern.

In the above UML diagram, let’s consider ‘IConvertor as a Target, that allows implementing to convert from one interface type to another.

Here ‘XMLReader’ as an adaptor has raw data converted to the required format.

Here ‘XML2JSONAdaptor’ as an Adaptee has the implementation to convert from one format to another. All the conversion logic will go here.

Define ‘Target’, Here Target as ‘IConvertor’ interface, that has the signature ‘Convert()’,

namespace DP.AdaptorDesignPattern.Target
{
    /// <summary>
    /// Defines the Target prototype
    /// </summary>
    public interface IConvertor
    {
        string Convert();
    }
}

Define ‘Adaptee’, Here Adaptee as ‘XMLReader’ class, that have the base format (XML Format) to convert.

namespace DP.AdaptorDesignPattern.Adaptor
{
    using System.IO;

    /// <summary>
    /// Represents the Adaptee : Here you will add to read unknown format
    /// </summary>
    public class XMLReader
    {
        public string Read(string path)
        {
            return File.ReadAllText(path);
        }
    }
}

Define ‘Adaptor’, Here Adaptor as ‘XML2JSONAdaptor’ class, that helps to convert from one format to another format (XML to JSON format),

namespace DP.AdaptorDesignPattern.Adaptor
{
    using Newtonsoft.Json;
    using System.Xml;
    using DP.AdaptorDesignPattern.Target;

    /// <summary>
    /// Represents the Adaptor: Converts into needed format
    /// </summary>
    public class XML2JSONAdaptor : XMLReader, IConvertor
    {
        private readonly string _path;
        public XML2JSONAdaptor(string path)
        {
            _path = path;
        }

        public string Convert()
        {
            //This is our in-compatibility format, i.e XML
            string xmlContent = base.Read(_path);

            //Here will be converting to required format, i.e. JSON
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xmlContent);
            return JsonConvert.SerializeXmlNode(doc);
        }
    }
}

Define ‘Client’, Here we need to consume the Adaptor (XML2JSONAdaptor) to convert from one format to another format.

namespace DP.AdaptorDesignPattern
{
    using System;
    using DP.AdaptorDesignPattern.Adaptor;

    public class Program
    {
        public static void Main(string[] args)
        {
            XML2JSONAdaptor adaptor = new XML2JSONAdaptor(@"..\..\Test.xml");
            var jsonData = adaptor.Convert();
            Console.WriteLine(jsonData);
            Console.ReadLine();
        }
    }
}

FYI - Below snap of input XML data(Test.xml).

Quick start on Adaptor Design Pattern

Output

The below output shows the data converted from XML to JSON. Here the key to remember is that when the existing system needs to communicate with a third-party system with a different format without breaking the existing system and builds Interoperability between the system, this kind of conversation can be achieved by Adaptor Design pattern.

Quick start on Adaptor Design Pattern

I hope this article helps you to understand the simple approach. Thanks for reading the article.