Adapter Design Pattern:
Software usually consists of a mixture of in-house and purchased
software that must work together to produce a seamless user
interface. But disparate software packages are not aware of each
other's object models, so they can't work together—without
adapters. Adapters let objects from unrelated software packages
collaborate by adapting one interface to another. Learn how the
Adapter design pattern can save you a lot of time and effort by
combining disparate software systems.
The Adapter pattern lets disparate object types work together.
Introducing Adapter
Adapters are necessary because dissimilar
elements need to interoperate. From wrenches to computer networks,
physical adapters
are abundant. In software, adapters make
dissimilar software packages work together; for example, you might have a
tree of
objects (call them
Nodes) you want to display using Swing's
JTree. The
JTree class can't display your
Nodes directly, but it can display
TreeNode instances. With an adapter, you can map your
Nodes to
TreeNodes. Because Swing trees use the Adapter pattern, you can display any kind of tree—from Document Object Model (DOM) to Swing
component hierarchies to a compiler parse tree—just by implementing a simple adapter.
In
Design Patterns, the authors describe the Adapter pattern like this:
Convert the interface of a class
into another interface clients expect. Adapter lets classes work
together that couldn't otherwise
because of incompatible interfaces.
Figures 2 and 3 show the Adapter pattern's two standard variations.

Figure 2. Adapter with inheritance. Click on thumbnail to view full-size image.

Figure 3. Adapter with delegation. Click on thumbnail to view full-size image.
Adapters masquerade as one type of object by implementing its interface; they inherit (or delegate) functionality from another
class. That way, you can effectively substitute objects (known as
Adaptees) for target (
Target) objects. For the
JTree in Figure 1, I adapt the objects in the tree (
UIComponents) to Swing, so a
JTree instance can manipulate them. Considering the amount of code that sits behind
JTree, this simple adapter provides a huge return on investment. Let's see how it works.
In Eclipse:
This pattern is used a lot in Eclipse, allowing plug-ins to be loosely coupled, yet still be integrated into the Eclipse runtime.
Adapters in the Real World
A real world analogy always helps
with the understanding of a design pattern. The best example for the
adapter pattern is based around AC power adapters. Say you're visiting
Europe from the US, with your laptop, which expects a US power supply.
To get your laptop plugged in, you're going to need to get a power
adapter that accepts your US plug and allows it to plug in to the
European power outlet. The AC adapter knows how to deal with both sides,
acting as a middleman - this is the adapter pattern.
The Adapter Pattern
The Adapter is known as a
structural pattern,
as it's used to identifying a simple way to realize relationships between entities. The
definition of Adapter provided in the original Gang of Four book on Design
Patterns states:
Convert the interface of a class into another interface clients expect.
Adapter lets classes work together that couldn't otherwise because of
incompatible interfaces.
Let's take a look at the classic diagram definition of the adapter pattern:

The
Target interface defines the domain specific interface that the
Client used, so the client collaborates with objects that implement the Target interface. On the other side of things, the
Adaptee is the existing interface that needs adapting in order for our client to interact with it. The
Adapter adapts the Adaptee to the Target interface - in other words, it translates the request from the client to the adaptee.
Let's take a look at the interactions in a sequence diagram:
In this example, as far as the Client is concerned it's just calling the
request method
of the Target interface, which the Adapter has implemented. In the
background however, the Adapter knows that to return the right result,
it needs to call a different method,
specificAdapteeRequest, on the Adaptee.
Note: the
pattern described here is the object adapter. There is a class adapter
pattern, but you need multiple inheritance to use it. Seeing as Java
doesn't support multiple inheritance, I'm going to leave this out.
Where Would I Use This Pattern?
The
main use of this pattern is when a class that you need to use doesn't
meet the requirements of an interface. As mentioned before, adapters are
common across Eclipse plug-ins. For a particular object to contribute
to the Properties view, adapters are used display the objects data. The
view itself doesn't need to know anything about the object the it is
displaying properties for.
Where Would I Use This Pattern?
The main use of this pattern
is when a class that you need to use doesn't meet the requirements of an
interface. As mentioned before, adapters are common across Eclipse
plug-ins. For a particular object to contribute to the Properties view,
adapters are used display the objects data. The view itself doesn't need
to know anything about the object the it is displaying properties for.
So How Does It Work In Java?
The following example
shows a simple implementation of the pattern. Consider that we have a
third party library that provides sorting functionality through it's
NumberSorter class. This is our
Adaptee.
01.
02.
03.
04.
05.public class NumberSorter
06.{
07.public List<Integer> sort(List<Integer> numbers)
08.{
09.
10.return new ArrayList<Integer>();
11.}
12.
13.}
Our
Client deals with primitive arrays rather than Lists.
For the sake of this example, lets say we can't change the client to use Lists.
1.int[] numbers = new int[]{34, 2, 4, 12, 1};
2.
3.Sorter sorter = new SortListAdapter();
4.sorter.sort(numbers);
We've provided a Sorter interface that expects the client input. This is our
target.
1.
2.public interface Sorter
3.{
4.public int[] sort(int[] numbers);
5.}
Finally, the SortListAdapter implements our target interface and deals with our adaptee, NumberSorter
01.public class SortListAdapter implements Sorter
02.{
03.
04.@Override
05.public int[] sort(int[] numbers)
06.{
07.
08.List<Integer> numberList = new ArrayList<Integer>();
09.
10.
11.NumberSorter sorter = new NumberSorter();
12.numberList = sorter.sort(numberList);
13.
14.
15.
16.return sortedNumbers;
17.}
18.
19.}
While this example may be overkill, it illustrates how the adapter pattern can work.
Watch Out for the Downsides
Some
say that the Adapter pattern is just a fix for a badly designed system,
which didn't consider all possibilties. While this is a fair point, it
is an important part of a pluggable architecture. It can also add a
level of complexity to your code, making debugging more difficult.