The adapter pattern is a structural design pattern that allows you to repurpose a class with a different interface, allowing it to be used by a system which uses different calling methods.
Adopter Design pattern
A square peg in a round hole
The Adapter pattern translates one interface for a class into a compatible interface. It is used when two classes could conceptually work together but cannot because of implementation details. For this example, I create a few simple classes modeling the problem of fitting a square peg into a round hole. A square peg will sometimes fit into a round hole, as illustrated in figure depending on the relative sizes of the peg and the hole:
To determine if a square will fit into a circle, I use the formula shown here
Figure 2. Formula for determining if a square will fit into a circle
I could trivially solve the square peg/round hole problem with a simple utility class that handles conversions. But it exemplifies a larger problem. For example, what if I’m adapting a Button to fit on a type of Panel that it wasn’t designed for yet can be made compatible with? The problem of square pegs and round holes is a convenience simplification of the general problem addressed by the Adapter design pattern: adapting two incompatible interfaces. To enable square pegs to work with round holes, I need a handful of classes and interfaces to implement the Adapter pattern, as shown in Listing 1:
Listing 1. Square pegs and round holes in Java
public class SquarePeg {
private int width;
public SquarePeg(int width) {
this.width = width;
}
public int getWidth() {
return width;
}
}
public interface Circularity {
public double getRadius();
}
public class RoundPeg implements Circularity {
private double radius;
public double getRadius() {
return radius;
}
public RoundPeg(int radius) {
this.radius = radius;
}
}
public class RoundHole {
private double radius;
public RoundHole(double radius) {
this.radius = radius;
}
public boolean pegFits(Circularity peg) {
return peg.getRadius() <= radius;
}
} |
To reduce the amount Java code, I’ve added an interface named Circularity to indicate that the implementer has a radius. This lets me write the RoundHole code in terms of round things, not just RoundPegs. This is a common concession in the Adapter pattern to make type resolution easier.
To fit square pegs into round holes, I need an adapter that adds Circularity to SquarePegs by exposing a getRadius() method, as shown in Listing 2:
Listing 2. Square peg adapter
public class SquarePegAdaptor implements Circularity {
private SquarePeg peg;
public SquarePegAdaptor(SquarePeg peg) {
this.peg = peg;
}
public double getRadius() {
return Math.sqrt(Math.pow((peg.getWidth()/2), 2) * 2);
}
} |
To test that my adapter does in fact let me fit suitably sized square pegs in round holes, I implement the test shown in Listing 3:
Listing 3. Testing adaptation
@Test
public void square_pegs_in_round_holes() {
RoundHole hole = new RoundHole(4.0);
Circularity peg;
for (int i = 3; i <= 10; i++) {
peg = new SquarePegAdaptor(new SquarePeg(i));
if (i < 6)
assertTrue(hole.pegFits(peg));
else
assertFalse(hole.pegFits(peg));
}
} |
In Listing 3, for each of the proposed widths, I wrap the SquarePegAdaptor around the creation of the SquarePeg, enabling hole’s pegFits() method to return an intelligent evaluation as to the fitness of the peg.
This code is straightforward, because this is a simple albeit verbose pattern to implement in Java. This paradigm is clearly the GoF design-pattern approach. However, the pattern approach isn’t the only way.
0.000000
0.000000