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.
-
- Client calls Adapter using using Target Interface.
- Adapter class translates this request and delegates it to adaptee using one/multiple method calls using Adaptee Interface.
- 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.