The Adapter Pattern converts the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
The Adapter Pattern is used when an existing adaptee class is needed and its interface is not the one a client needs. For this, the pattern changes an intefcace into one a client expects using a adapter class. To achieve this, there are two forms of the Adapter Pattern: object and class adapters. Class adapters require multiple inheritance. They inherit from the adaptee and the target interface, which is expected by the client. With the object adapter, the adapter implements the target interface and wraps the adaptee by holding an instance of it.
The client is implemented against the target interface and uses the adapter in the following way:
- The client makes a request to the adapter by calling a method on it using the target interface.
- The adapter translates the request into one or more calls on the adaptee using the adaptee interface
- The client receives the results of the call and never knows there is an adapter doing the translation.
Another way to implement an adapter in programming languages that support multiple inheritance like C++ is to let the adapter class inherit both the target interface and the adaptee. This is known as Class Adapter. An Object Adapter uses composition to pass requests to an Adaptee.
Adapters are similar to the Facade Pattern and the Decorator Pattern. An adapter wraps an object to change its interface, a decorator wraps an object to add new behaviors and responsibilities, and a facade “wraps” a set of objects to simplify.
The following example uses modified classes found in the example of the Strategy Pattern. Here we have the following classes. A Duck interface acting as the target interface that a client expects to see:
An implementation of this target interface is the
The object that we are going to adapt, the adaptee, is the following
A concrete implementation of this interface is
The followign main program uses adapters to adapt a
Turkey to a
The adapter that is used here converts a
Turkey to a
Duck. Therefore it needs to implement the target interface
It has a reference to its adaptee, the
Turkey, which is initialized through the constructor. The class implements the methods of its target interface using the adaptee reference:
The output of the program is:
Another real-life example is to use an adapter between Java iterators and enumerators.
In Java, early collection types (Vector, Stack, Hashtable, and a few others) implement a method,
which returns an
Enumeration interface allows you to step through the elements of a collection
without knowing the specifics of how they are managed in the collection.
In later versions of Java this was replaced with
Iterators which has also a
To deal with legacy code, that exposes the
Enumeration interface, yet we’d like for our new code to use only
An adapter to deal with this situation would need to implement the
Iterator as its target interface and be composed with
Enumeration as its adaptee:
next() methods are straightforward to map from target to adaptee: we just pass them right through. The best we can do for
remove() is to throw a runtime exception because
Enumeration does not support removing.
The following code test the above