Adapter pattern is a structural pattern. Here is the definition:
Convert the interface of a class into another interface clients expect.
Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.
In other words, clients expect A, but all we’ve got is B, and yet we want to reuse B, so we introduce an adapter for B, allowing clients to use B in the way they use A without making changes to their code. Note that the adapter does not change the underline behavior implemented by B.
UML diagram and implementation
This is one way of implementing adapter pattern using composition. It is called Object Adapter.
Object adapter
Note that Adaptee can be a class or interface.
1 | public interface Target { |
1 | public class Adaptee { |
1 | public class Adapter implements Target { |
1 | Target obj = new Adapter(new Adaptee()); |
And there is another way called Class Adapter. It uses inheritance instead of composition.
Class adapter
Since Java (before JDK 8), I’m not quite sure how this is implemented in Java yet.
Object adapter vs. Class adapter
Another argument about “composition over inheritance”. Check this if you’re insterested.
Real Examples
In the examples below, what the adapter does is to convert the input from one format to another so that the client can deal with the output format rather than the input format.
i. Java API: java.io.InputStreamReader
As we know, BufferedReader expects a character stream, and InputeStream provides byte stream only, how can we make BufferedReader read data from InputStream without changing their implementation? The answer is to introduce an adapter as a wrapper for InputStream. As shown below, InputStreamReader serves as an adapter which converts byte stream into character stream, so the data from InputStream can be handled by BufferedReader.
1 | URLConnection conn = new URL("http://google.com").openConnection(); |
ii. JAXB: javax.xml.bind.annotation.adapters.XmlAdapter
XmlAdapter ensures that every type can be handled by JAXB, that is, if JAXB cannot map an object to an XML representation, the object will be converted from one type to another which JAXB can map to an XML representation. This is done by creating an adapter class which extends XmlAdapter and having the method marshal() and unmarshal() implemented, and this adapter class will be called when the mapping is needed. More details can be found in this post about how to use XmlAdapter.