Adapter - kgleong/software-engineering GitHub Wiki
The Adapter
design pattern allows translation from one API to another.
This pattern is usually applied when an existing class's interface does not conform to the desired interface.
public interface Target {
void performOperation();
}
The Target
interface specifies the API utilized by clients.
public class Adaptee {
public void performAdapteeOperation() {
System.out.println("Adaptee is doing work.");
}
}
Currently, the Adaptee
does not conform to the to the Target
interface.
public class Adapter implements Target {
private Adaptee mAdaptee;
public Adapter(Adaptee adaptee) {
mAdaptee = adaptee;
}
public void performOperation() {
// Translate adaptee's API to target API.
mAdaptee.performAdapteeOperation();
}
}
As a result, an intermediary Adapter
class is used, which does the following:
- Wraps the non-conforming
Adaptee
class. - Conforms to the
Target
interface. - Performs any translation necessary between the
Adaptee
andTarget
APIs.
public interface Shape {
double getArea();
}
The Shape
interface defines the desired API that both the Circle
and Rectangle
classes below need to abide by.
public class Circle implements Shape {
int mRadius;
public Circle(int radius) {
mRadius = radius;
}
public double getArea() {
return Math.PI * Math.pow(mRadius, 2);
}
}
public class Rectangle {
// Public access to simplify example.
public int width;
public int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
}
The Circle
class already conforms to the Shape
API, but the Rectangle
class does not.
This may be due to the fact that the Rectangle
class is part of an external library, or has some other contractual obligations.
Because of this, the Rectangle
class cannot be modified directly, but it still needs to be adapted to conform to the Shape
interface.
public class RectangleShapeAdapter implements Shape {
Rectangle mRectangle;
public RectangleShapeAdapter(Rectangle rectangle) {
mRectangle = rectangle;
}
public double getArea() {
return mRectangle.width * mRectangle.height;
}
}
The RectangleShapeAdapter
class solves this translation, by wrapping a Rectangle
instance and implmeenting the required getArea()
method.
Shape circle = new Circle(5);
Rectangle rectangle = new Rectangle(2, 3);
Shape rectangleShape = new RectangleShapeAdapter(rectangle);
List<Shape> shapeList = new ArrayList<>();
shapeList.add(circle);
shapeList.add(rectangleShape);
for(Shape shape : shapeList) {
System.out.println("Area is: " + shape.getArea());
}
This allows Rectangle
instances to now be treated as any Shape
object would be.