The Adapter pattern alters an interface of a class into another interface. So when there’s a Type B interface, but Type A is expected, Adapter pattern helps to convert Type B into Type A. This makes classes with different interfaces to compatible and interchangeable.
To make this working, Type B is wrapped into an adapter class that implements Type A interface and stores a reference to Type B in a field. When a method of this class is invoked that belongs to Type A, that calls a method on Type B.
Adapter pattern is a structural pattern.
Let’s see a Java example for the Adapter pattern.
The next example is about two type of boats and one type of boat driver. There’s a motorboat driver, which is actually a method that receives a motorboat as parameter and drives it. Suddenly a sailboat appears, but the driver cannot handle it. A motorboat driver doesn’t know how to use a sail, how to steer a sailboat and so on. So there are two type of boats, and an adapter is needed to convert the sailboat to a motorboat. After that, the driver will be able to manage it.
First define the Motorboat
interface.
package com.programcodex.designpatterns.adapter;
public interface Motorboat {
void startEngine();
void stopEngine();
void steering();
}
After that, create a class that implements the above interface.
For example, it can be a ClassicWoodenMotorboat
class.
package com.programcodex.designpatterns.adapter;
public class ClassicWoodenMotorboat implements Motorboat {
@Override
public void startEngine() {
System.out.println("Starting the engine.");
}
@Override
public void stopEngine() {
System.out.println("Stopping the engine.");
}
@Override
public void steering() {
System.out.println("Steering the motorboat.");
}
}
In the next step, make another interface for the Sailboat
.
package com.programcodex.designpatterns.adapter;
public interface Sailboat {
void raiseSail();
void lowerSail();
void setSail();
void steering();
}
Let’s also give an implementation for it. Now, that will be the YachtSailboat
class.
package com.programcodex.designpatterns.adapter;
public class YachtSailboat implements Sailboat {
@Override
public void raiseSail() {
System.out.println("Raising the sail and go.");
}
@Override
public void lowerSail() {
System.out.println("Lowering the sail and slowing down.");
}
@Override
public void setSail() {
System.out.println("Setting the sail.");
}
@Override
public void steering() {
System.out.println("Steering the sailboat.");
}
}
It’s time to create the Adapter class.
The Sailboat
has to be altered to a Motorboat
.
For that the Sailboat
gets wrapped into a class that implements
the Motorboat
interface. The Motorboat
methods call
the appropriate methods of the Sailboat
class to get the job done.
For example, when the Motorboat driver starts the engine on a Sailboat, actually the sail is raising.
package com.programcodex.designpatterns.adapter;
public class SailboatAdapter implements Motorboat {
private Sailboat sailboat;
public SailboatAdapter(Sailboat sailboat) {
this.sailboat = sailboat;
}
@Override
public void startEngine() {
sailboat.raiseSail();
}
@Override
public void stopEngine() {
sailboat.lowerSail();
}
@Override
public void steering() {
sailboat.steering();
sailboat.setSail();
}
}
And we are done. It’s time to run these things.
The driveMotorboat
method receives a Motorboat
parameter.
The ClassicWoodenMotorboat
can be passed to it,
but it doesn’t accept the YachtSailboat
class.
To solve this problem, the latter one has to be wrapped by a SailboatAdapter
class.
package com.programcodex.designpatterns.adapter;
public class TestAdapter {
public static void main(String[] args) {
Motorboat motorboat = new ClassicWoodenMotorboat();
Sailboat sailboat = new YachtSailboat();
System.out.println("A motorboat driver is here.");
System.out.println("He can drive the motorboat:\n");
driveMotorboat(motorboat);
System.out.println("\nBut he can't manage a sailboat.");
System.out.println("No problem. An adapter will help here:\n");
Motorboat sailboatAdapter = new SailboatAdapter(sailboat);
driveMotorboat(sailboatAdapter);
}
private static void driveMotorboat(Motorboat motorboat) {
motorboat.startEngine();
motorboat.steering();
motorboat.stopEngine();
}
}
The output of the above test class: