Let us return to the consideration of structural design patterns. This time we will look at a design pattern called Adapter (also called the Wrapper along with the Facade pattern).
This article will talk about the following:
Object adapter
Class Adapter
The difference between the adapter and the facade
An example of using an adapter in the JDK
So, the Adapter pattern is used so that objects with one interface (contract) can work where an object with a completely different interface is needed. There are two types of adapters – the Class Adapter and the Object Adapter.
To begin, we will look at each of these types, and then I will explain the difference between the two wrappers — the adapter and the front.
Object adapter
The Object Adapter achieves its goal with composition. In the diagram below, the client needs to use the TargetInterface interface. For this, an ObjectAdapter class is created that implements the TargetInterface interface and also stores an object of the Adaptee class. When calling the Adapter’s targetMethod method, the corresponding method of the adaptable interface is called.
public class ObjectAdapter implements TargetInterface { private Adaptee adaptee; public void targetMethod() { adaptee.method() } }
The advantage of this approach is that we completely separate the client interface from the interface being adapted.
Class Adapter
In the case of the Class Adapter, multiple inheritance is used to achieve our goal. Our ClassAdapter is inherited from the client interface and from the Adaptable interface. Since there is no multiple inheritance in Java, only one of the ancestors can be an abstract / concrete class. The second ancestor will be the interface, which is not always convenient.
Class diagram:
And here is a trivial implementation of the ClassAdapter class:
public class ClassAdapter extends Adaptee implements TargetInterface { public void targetMethod() { method(); } }
I want to draw your attention to the fact that with such an implementation of the adapter there may be a conflict between method methods. There is no such problem for the Object Adapter.
A Class Adapter is considered to be a simpler solution in the case when a hard separation of client and adaptable interfaces is not required.
The Difference Between the Adapter and the Facade
Now I want to say a few words about the Facade pattern, which, like the Adapter, is a Wrapper. Facade defines a new interface, while the Adapter uses existing interfaces.
You should not compare the Facade and the Adapter as follows: they say, the Facade can wrap several classes, and the Adapter adapts only one. It may well be that the Adapter will be needed to adapt several classes and vice versa, the Facade will have to be used to simplify only one complex class. So the difference between these two patterns is not in the number of entities wrapped, but in what they are doing.
An example of using an adapter in JDK
In the standard library, you can also find examples of using the Adapter. Probably the most popular use case is java.io.InputStreamReader and OutputStreamWriter.
The InputStreamReader constructor accepts an InputStream input and, as a result, adapts the stream to Reader.