Adapter Pattern

Adapter Pattern is the Structural pattern.

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

Real Life Example:

AC Power Adapters

Electronic products made for the USA cannot be used directly with electrical outlets found in most other parts of the world. US 3-prong (grounded) plugs are not compatible with European wall outlets.
 To use, you need either
• An AC power adapter, if the US product has a “universal” power supply, or
• An AC power converter/adapter, if it doesn’t

Type of Adapter:

Object Adapters
Object Adapters use a compositional technique to adapt one interface to another. The adapter inherits the target interface that the client expects to see, while it holds an instance of adaptee. Object adapters enable the client and the adaptee to be completely decoupled from each other. Only the adapter knows about both of them.

Class Adapters
Class adapters use multiple inheritance to achieve their goals. As in the object adapter, the class adapter inherits the interface of the client’s target. However, it also inherits the interface of the adaptee as well. Since Java  does not support true multiple inheritance, this means that one of the interfaces must be inherited from a Java Interface type. Note that either or both of the target or adaptee interfaces could be a Java Interfaces. The request to the target is simply rerouted to the specific request that was inherited for the adaptee interface.

Object Adapters Vs. Class Adapters

  • As Object Adapter uses composition it can not only adapt an adaptee class, but any of its subclasses. It is flexible.
  • Class Adapter is committed to only one adaptee. But again it has an advantage as no need to implement the entire adaptee. It can just override the behaviour of adaptee and also can override the behavior as it is sub classing.
  • Class adapters are simpler than object adapters in that they involve fewer classes and are useful if total decoupling of the client and adaptee is not needed.
  • Note that class adapters have a problem with name conflicts if methods of the same signature exist on both the target and the adaptee. Note that just because two objects have methods that have the same signature (syntax), it does not guarantee that the two methods have the same meaning or behavior (semantics). That is, the two methods do not necessarily map directly to each other. Object adapters do not have this problem.

Case Study

Client only understands the SquarePeg interface for inserting pegs using the insert() method. At back-end application should reuse insert logic within round pegs?

Solution
One Way Adaptor (Object Adaptor)
Two Way Adaptor (Class Adaptor)

Class Diagram: Please open class diagram in new window if problem occurs.

Adapter Pattern

Adapter Pattern

Explanation:

  1. The client makes a request on the adapter by invoking a method from the target interface on it
  2. The adapter translates that request into one or more calls on the adaptee using the adaptee interface
  3. The client receives the results of the call and never knows there is an adapter doing the translation

Code:

One Way Adapter Example

Target Class

package com.structural.adaptor.simple;

/**
 * The SquarePeg class.
 * This is the Target class.
 * Client only understands the SquarePeg interface for inserting pegs using 
 * the insert() method.
 */
public class SquarePeg {
 public void insert(String str) {
  System.out.println(“SquarePeg insert(): ” + str);
 }
}

Adaptee Class

package com.structural.adaptor.simple;
/**
* The RoundPeg class.
* This is the Adaptee class.
*/
public class RoundPeg {
 public void insertIntoHole(String msg) {
  System.out.println(“RoundPeg insertIntoHole(): ” + msg);
 }
}

Adapter Class

package com.structural.adaptor.simple;
/**
* The PegAdapter class.
* This is the Adapter class.
* It adapts a RoundPeg to a SquarePeg.
* Its interface is that of a SquarePeg.
*/
public class PegAdapter extends SquarePeg {
 private RoundPeg roundPeg;
 public PegAdapter(RoundPeg peg) {this.roundPeg = peg;}
 public void insert(String str) {
  roundPeg.insertIntoHole(str);
 }
}

Client Class

package com.structural.adaptor.simple;
/**
 * Test program for Pegs.
 */
public class AdaptorClient {
 public static void main(String[] args) {
  // Create some pegs.
  RoundPeg roundPeg = new RoundPeg();
  SquarePeg squarePeg = new SquarePeg();
  // Do an insert using the square peg.
  squarePeg.insert(“Inserting square peg… With SquarePeg.”);
  /*
   * Now we’d like to do an insert using the round peg. But this client
   * only understands the insert() method of pegs, not a insertIntoHole()
   * method. The solution: create an adapter that adapts a square peg to a
   * round peg!
   */
  PegAdapter adapter = new PegAdapter(roundPeg);
  adapter.insert(“Inserting round peg… With PegAdapter.”);
 }
}

Two Way Adapter Example

Target and Adaptee Interface/Implementation

package com.structural.adaptor.twowayadaptor;

/**
 * The IRoundPeg interface.
 */
public interface IRoundPeg {
 public void insertIntoHole(String msg);
}

package com.structural.adaptor.twowayadaptor;

/**
 * The ISquarePeg interface.
 */
public interface ISquarePeg {
 public void insert(String str);
}

package com.structural.adaptor.twowayadaptor;
/**
* The RoundPeg class.
*/
public class RoundPeg implements IRoundPeg{
 public void insertIntoHole(String msg) {
  System.out.println(“RoundPeg insertIntoHole(): ” + msg);
 }
}

package com.structural.adaptor.twowayadaptor;

/**
 * The SquarePeg class.
 */
public class SquarePeg implements ISquarePeg{
 public void insert(String str) {
  System.out.println(“SquarePeg insert(): ” + str);
 }
}

Adapter Class

package com.structural.adaptor.twowayadaptor;
/**
* The PegAdapter class.
* This is the two-way adapter class.
*/
public class PegAdapter implements ISquarePeg, IRoundPeg {
 private RoundPeg roundPeg;
 private SquarePeg squarePeg;
 
 public PegAdapter(RoundPeg peg) {this.roundPeg = peg;}
 public PegAdapter(SquarePeg peg) {this.squarePeg = peg;}
 
 public void insert(String str) {
  roundPeg.insertIntoHole(str);
 }

 public void insertIntoHole(String msg) {
  squarePeg.insert(msg);
 }

}

Client

package com.structural.adaptor.twowayadaptor;
/**
 * Test program for Pegs.
 */
public class TestPegs {
 public static void main(String[] args) {
   // Create some pegs.
   RoundPeg roundPeg = new RoundPeg();
   SquarePeg squarePeg = new SquarePeg();
   // Do an insert using the square peg.
   squarePeg.insert(“Inserting square peg… With SquarePeg.”);
   // Create a two-way adapter and do an insert with it.
   ISquarePeg roundToSquare = new PegAdapter(roundPeg);
   roundToSquare.insert(“Inserting round peg… With ISquarePeg.”);
   // Do an insert using the round peg.
   roundPeg.insertIntoHole(“Inserting round peg… With RoundPeg.”);
   // Create a two-way adapter and do an insert with it.
   IRoundPeg squareToRound = new PegAdapter(squarePeg);
   squareToRound.insertIntoHole(“Inserting square peg… With IRoundPeg.”);
 }
}

Where To Use

We can not change the library interface, since we may not have its source code. Even if we did have the source code, we probably should not change the library for each domain-specific application.
Sometimes a toolkit or class library can not be used because its interface is incompatible with the interface required by an application.
Want to create a reusable class that cooperates with unrelated classes with incompatible interfaces.

Implementation Issues
How much adapting should be done?
Simple interface conversion that just changes operation names and order of arguments
Totally different set of operations

Does the adapter provide two-way transparency?
A two-way adapter supports both the Target and the Adaptee interface. It allows an adapted object (Adapter) to appear as an Adaptee object or a Target object.

Should Read: Decorator Pattern, Bridge PatternFaçade Pattern

Comparison:

Adapter Pattern Vs Decorator Pattern

Adapter and Decorator’s similarity?

  • They both wrap objects at run-time
  • They both delegate requests to their wrapped objects

Adapter and Decorator are different?

  • Adapter converts one interface into another while maintaining functionality (extends Target, compose Adaptee)
  • Decorator leaves the interface alone but adds new functionality (extends and compose Object to decorate)
  • Decorators are designed to be “stacked”; that’s less likely to occur with

Adapter Pattern Vs Façade Pattern

Adaptor and Façade similarity?

  • Both facades and adapters may wrap multiple classes

Adaptor and Façade are different?

  • Adapter converts one interface into another while maintaining functionality
  • The Facade Pattern provides a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
  • Facade’s intent is to simplify, while an adapter’s is to convert between interfaces

Adapter Pattern Vs Bridge Pattern

Adaptor and Bridge are different?

  • Bridge pattern separates the interface from implementation. 
  • Bridge pattern should be used when both the class as well as what it does very often.
  • Abstractions and implementations should not be bound at compile time, and should be independently extensible the pattern should be used.

Case Study Problem (To Try):

Simulate banking application where user input data from UI. Data can be saved within application database and/or routed to mainframe. Mainframe is proprietary system and we do not have control over same.

Requirement

If user do inter bank account transfer data will be saved within database (batch will be used for sending EFT data via ACH) and mainframe to reflect real-time account balance.

Hint (where Adapter can be used?): Write Adapter over business Object which is used to interact within Mainframe. Note – Data Object for database persistence should be generic I.e. as per Financial Standard where as MainFrame was build 20 years back.

Please share your feedback/query.

Should Read: Decorator Pattern, Bridge PatternFaçade Pattern

Next In Store: Bridge Pattern

Download Code: AdaptorPattern.zip

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: