Adapter Design Pattern

The Adapter Pattern Convert the interface of a class into another interface clients expect. It enables a client with incompatible interface to interact with existing class using an intermediate Adapter class. An Adapter class acts like a middle man through which two classes having incompatible interfaces can interact with each other. It comes under structural design pattern as it facilitates communication between two interfaces.

Advantages of Adapter Pattern

  • Two classes having incompatible interfaces can interact with each other using an Adapter class.
  • It promotes reusability of existing system. A class can be accessed by multiple systems using different interfaces and Adapters.

When we should use Adapter pattern

  • When client wants to interact with existing system using incompatible interface.
  • When a new system wants to interact with legacy(old) system using new interface which is not compatible with interface of legacy system.
  • When you want to use a 3rd party framework or library whose interface is incompatible with your system.

Components of Adapter Pattern

  • Target Interface : This is the interface expected by the client.
  • Adapter : This is a wrapper over Adaptee class which implements the Target Interface. It receives calls from the client and translates that request to one/multiple adaptee calls using Adaptee interface.
  • Adaptee Interface : This is the existing interface which is wrapped by Adapter. Client wants to interact with Adaptee but cannot interact directly because Adaptee Interface is incompatible with Target Interface.
  • Client : Client will interact with Adapter using Target Interface.
  1. Client calls Adapter using using Target Interface.
  2. Adapter class translates this request and delegates it to adaptee using one/multiple method calls using Adaptee Interface.
  3. Adaptee returns response to Adapter class as defined in Adaptee Interface and then Adapter transforms this response before returning it to Client as defined in Target Interface.

We will declare two incompatible interfaces Square and Rectangle.

Square.java
public interface Square {
    public void setSide(int sideLength);
    public void printAreaOfSquare();
}
Rectangle.java
public interface Rectangle {
    public void setLength(int length);
    public void setWidth(int width);
    public void printAreaOfRectangle();
}

Create Chessboard.java and Tenniscourt.java implementing Square and Rectangle interfaces respectively.

Chessboard.java
public class Chessboard implements Square {
    int sideLength;
 
    @Override
    public void setSide(int sideLength){
        this.sideLength = sideLength;
    }
 
    @Override
    public void printAreaOfSquare(){
        System.out.println("Area of Chessbpard is " + sideLength*sideLength);
    }
}
Tenniscourt.java
public class Tenniscourt implements Rectangle {
    int length, width;
 
    @Override
    public void setLength(int length){
        this.length = length;
    }
 
    @Override
    public void setWidth(int width){
        this.width = width;
    }
 
    @Override
    public void printAreaOfRectangle(){
        System.out.println("Area of Tennis Court is " + length*width);
    }
}

Now, we will define RectangleAdapter.java which is a wrapper over Rectangle interface. It implements Square interface over Rectangle Interface.

RectangleAdapter.java
public class RectangleAdapter implements Square {
    Rectangle rect;
 
    public RectangleAdapter(Rectangle rect) {
        this.rect = rect;
    }
 
    // Setting length and width to same value to make it a square
    @Override
    public void setSide(int sideLength){
        rect.setLength(sideLength);
        rect.setWidth(sideLength);
    }
 
    @Override
    public void printAreaOfSquare(){
        rect.printAreaOfRectangle();
    }
}

Create AdapterPatternExample.java class to show the use of RectangleAdapter to call an Rectangle object using Square interface.

AdapterPatternExample.java
public class AdapterPatternExample {
    public static void main(String args[]){
        Square square = new Chessboard();
        Rectangle rectangle = new Tenniscourt();
        Square adapter = new RectangleAdapter(rectangle);
 
        // Calculate Area of Square using Square Interface 
        square.setSide(5);
        square.printAreaOfSquare();
  
        // Calculate Area of Rectangle using Rectangle Interface
        rectangle.setLength(5);
        rectangle.setWidth(4);
        rectangle.printAreaOfRectangle();
  
        // Now we will call Rectangle object using Square interface 
        adapter.setSide(5);
        adapter.printAreaOfSquare(); 
    }
}

Output

Area of Chessbpard is 25
Area of Tennis Court is 20
Area of Tennis Court is 20

Important Points About Adapter Pattern
  • Adapter class changes the interface of an existing object.
  • Adapter class is a good example of object composition. Adapter class "has a" instance of the adaptee class.
  • We can use an Adapter with any class Implementing Adaptee Interface.
  • Adapter wraps an object to change it's interface whereas a decorator wraps an object to add extra functionalities.

Related Topics
Interpreter Design Pattern
State Design Pattern
Singleton Design Pattern
Factory Design Pattern
Mediator Design Pattern
Observer Design Pattern
Bridge Design Pattern
Prototype Design Pattern
Memento Design Pattern
Filter Design Pattern
List of Design Patterns