Friday, January 11, 2013

Adapter Design Pattern

The Adapter pattern helps in Integrating 2 classes which have altogether different Interfaces. It’s useful for off-the-shelf code, for toolkits, and for libraries.  Generally Toolkit or 3rd Party controls needs a lot of adaptor classes as in many scenario it’s not possible to use Toolkit’s interfaces.

Design:
In following UML class diagram , we have a Client class and Adaptee class. Adaptee class has method “SepecificRequest” which needs to be called by Client class. Client class uses an Adaptor class which implements ITarget interface and exposes Request method. Adapter class implements Request method and it’s a child object in Client Class. So, Client doesn’t need to know anything about Adaptee class all it has to know is about ITarget interface and Request method.


Implementation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    // Existing way requests are implemented
    class Adaptee
    {
        // Provide full precision
        public double SpecificRequest(double a, double b)
        {
            return a / b;
        }
    }

    // Required standard for requests
    interface ITarget
    {
        // Rough estimate required
        string Request(int i);
    }

    // Implementing the required standard via Adaptee
    class Adapter : Adaptee, ITarget
    {
        public string Request(int i)
        {
            return "Rough estimate is " + (int)Math.Round(SpecificRequest(i, 3));
        }
    }

    class Client
    {
        public void CallRequest()
        {
            // Showing the Adapteee in standalone mode
            Adaptee first = new Adaptee();
            Console.Write("Before the new standard\nPrecise reading: ");
            Console.WriteLine(first.SpecificRequest(5, 3));

            // What the client really wants
            ITarget second = new Adapter();
            Console.WriteLine("\nMoving to the new standard");
            Console.WriteLine(second.Request(5));
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Client cl = new Client();
            cl.CallRequest();
            Console.Read();
        }
    }
}


Output:


Depending on their Usage, there are following 2 types of Adapter classes

1) Pluggable Adapters : Developers who recognize that their systems will need to work with other components can increase their chances of adaptation. Identifying in advance the parts of the system that might change makes it easier to plug in adapters for a variety of new situations.

Keeping down the size of an interface also increases the opportunities for new
systems to be plugged in. Although not technically different from ordinary adapters, this feature of small interfaces gives them the name pluggable adapters.
A distinguishing feature of pluggable adapters is that the name of a method called by the client and that existing in the ITarget interface can be different. The adapter must be able to handle the name change. In the previous adapter variations, this was true for all Adaptee methods, but the client had to use the names in the ITarget interface.
Suppose the client wants to use its own names, or that there is more than one client and they have different terminologies.



2) Two-Way Adapters : Adapters provide access to some behavior in the Adaptee (the behavior required in the ITarget interface), but Adapter objects are not interchangeable with Adaptee objects. They cannot be used where Adaptee objects can because they work on the implementation of the Adaptee, not its interface. Sometimes we need to have objects
that can be transparently ITarget or Adaptee objects. 

This could be easily achieved if the Adapter inherited both interfaces; however, such multiple inheritance is not possible in C#, so we must look at other solutions.

The two-way adapter addresses the problem of two systems where the characteristics of one system have to be used in the other, and vice versa. An  Adapter class is set up to absorb the important common methods of both and to provide adaptations to both. The resulting adapter objects will be Acceptable to both sides. Theoretically, this idea can be extended to more than two systems, so we can have multiway adapters, but there are some implementation limitations: without multiple inheritance, we have to insert an interface between each original class and the adapter.

No comments:

Post a Comment