Thursday, February 16, 2012

Design Pattern : Adapter Pattern Implementation

What is the Adapter Pattern?


The Adapter pattern is a structural design pattern which enables a system to use classes whose interfaces don’t quite match its requirements or in other words is used to make an interface which the client understands.

When to Use It?


  • It's quite useful when dealing with the legacy code especially that was written a while ago and to which one might not have access.
  • It is especially useful for off-the-shelf code, for toolkits, for libraries or any third party software.

Many of us use the enterprise library data access application block. Suppose later if we find that some other third party data access application block is better than Microsoft data access application block, then the project would not change just adapter internally would call the new data access application block.

Object Adapter Pattern


In Object adapter pattern, the adapter contains an instance of the class it wraps. In this situation, the adapter makes calls to the instance of the wrapped object.

// Existing class.. this may be your legacy code or third party code
class Adaptee
{
    // validates the email
    public bool IsEmail(string email)
    {
        return System.Text.RegularExpressions.Regex.IsMatch
  (email, @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*");
    }
}

// Required standard implementing through interface
interface ITarget
{
    // Rough estimate required
    bool ValidateEmail(string email);
}
// Implementing the required standard via Adaptee
class Adapter : Adaptee, ITarget
{
    public bool ValidateEmail(string email)
    {
        return IsEmail(email);
    }
}

class Client
{
    static void Main()
    {
        // Showing the Adaptee in standalone mode
        Adaptee first = new Adaptee();
        Console.Write("Before the new standard: ");
        Console.WriteLine(first.IsEmail("anyemail@gmail.com"));

        // What the client really wants
        ITarget second = new Adapter();
        Console.WriteLine("\nMoving to the new standard");
        Console.WriteLine(second.ValidateEmail("anyemail@gmail.com"));
    }
} 

  • ITarget: The interface that the Client wants to use
  • Adaptee: An implementation that needs adapting
  • Adapter: The class that implements the ITarget interface in terms of the Adaptee
  • ValidateEmail: An operation that the Client wants
  • IsEmail: The implementation of Request’s functionality in the Adaptee

Note


The adapter pattern is also useful where an already existing class provides some or all of the services you need but does not use the interface you need. Also using this way, you can change third-party library easily without affecting your project. In the above example, if you want to change the validation method of email, all you need to do is to use ValidateEmail function for any new method or third party library functions.

Another Example:

Definition

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

Note: 
  1. Wrap an existing class with a new interface.
  2. Impedance match an old component to a new system
  3. Adapter, the modifier, is about creating an intermediary abstraction that translates, or maps to the old component to the new system. Clients call methods on the Adapter object which redirects them into calls to the legacy component. This strategy can be implemented either with inheritance or with aggregation.
  4. Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an improved interface.
Design

Please refer to the code

Some of best example: Adaptor for Two pin plug, We can have only one adaptor

UML Diagram

From GoF

1.gif

2.gif


Code

/// <summary>
/// Target Wraper base
/// </summary>
public class AdaptorTarget
{
    public virtual void Request()
    {
        Console.WriteLine("Called Target Request()");
    }
}

/// <summary>
/// Adapter -- Wrapper
/// </summary>
public class Adaptor : AdaptorTarget
{
    internal OldSystem.Adaptee Adaptee
    {
        get { return new OldSystem.Adaptee();}
        set { ;}
    }
    public override void Request()
    {
        Adaptee.OldMethod();
    }
}

namespace OldSystem
{
    /// <summary>
    /// Adaptee -- Old system
    /// </summary>
    internal class Adaptee
    {
        internal void OldMethod()
        {
            Console.WriteLine("Called incompatable system method....");
        }
    }
}

Client

internal static AdaptorTarget AdaptorTargetLocal
{
    get
    {
        return new Adaptor();
    }
    set
    {
    }
}
static void Main(string[] args)
{
    AdaptorTargetLocal.Request();
}


Reference:

No comments:

Post a Comment