What is Adapter Design Pattern
The Adapter Design pattern is use when a client expects interfaceA but is provided with interfaceB. The adapter maps the methods from interfaceB to interfaceA. This pattern is used when the client expects certain methods in an interface or class(adaptee) but the adaptee does not provide those methods (Note that the adaptee does provide the required business logic but the methods that it exposes is different from what a client expects.).
Example of Adapter Design Pattern
We can understand Adapter design pattern using the real life example of travel adapters. If you have a British plug but an American socket then you are in trouble. The client (British plug) expects the socket (adaptee) to provide electrical connection. The socket does that but unfortunately the client (plug) cannot ‘connect to'(call methods of) the socket. In comes the Adapter to the rescue! The adapter has two characteristics. First, it can accept British plugs and second it can connect to American sockets. Its only role is to connect to both the client (plug) and the adaptee (socket) and to pass electricity between them (method call)
Lets develop this into an example. Here are the various classes
The Client is the British Plug with British Pin
package com.studytrails.patterns.adapter; public class BritishPlugClient { BritishPinType britishPin; private SocketAdapter adapter; public static void main(String[] args) { BritishPlugClient plug = new BritishPlugClient(); plug.connectToSocket(); } private void connectToSocket() { adapter = new SocketAdapter(); adapter.provideElectricity(britishPin); } }
The Target is the British Socket.
package com.studytrails.patterns.adapter; public interface BritishSocketTarget { void provideElectricity(BritishPinType britishPin); }
The Adaptee is the American Socket
package com.studytrails.patterns.adapter; public interface AmericanSocketAdaptee { void provideElectricity(AmericanPinType americanPin); }
The adapter to adapt between American And British Pins
package com.studytrails.patterns.adapter; public class SocketAdapter implements BritishSocketTarget { AmericanPinType americanPin; private AmericanSocketAdapteeImpl americanSocket; @Override public void provideElectricity(BritishPinType britishPin) { transferCurrent(britishPin, americanPin); americanSocket = new AmericanSocketAdapteeImpl(); americanSocket.provideElectricity(americanPin); } private void transferCurrent(BritishPinType britishPin, AmericanPinType americanPin) { // the adapter provides circuit the allows the electricity to flow from // a British pin to American pin. } }
The actual implementation of the American Socket Interface
package com.studytrails.patterns.adapter; public class AmericanSocketAdapteeImpl implements AmericanSocketAdaptee { @Override public void provideElectricity(AmericanPinType americanPin) { System.out.println("Enjoy Electricity"); } }
Heres’s the class diagram of adapter pattern.
- In The example above the Adapter implements the Adaptee interface and hence its referred to as a
class adapter
. - It would be good if the adapter can also be used for American plugs. Then we dont have to remove the adapter from the socket everytime we want to use an American plug after a British one. To be able to do that we can have the adapter implement both the American Socket as well as the British Socket. This is referred to as a
Two way adapter
- The Adapter can also extend the AmericanSocketImpl class instead of implementing the AmericanSocket interface. This would be an
Object adapter
. - Sometimes the Adapter does not need to know the adaptee. That is, it does not need to extend or implement adaptee interface or its classes. We could just pass the adaptee to the adaptor and provide a map that says that method A from the client needs to be forwarded to method B from the adaptee. Of course, to get access to the method B the adapter will have to use the reflection API. This is known as the
pluggable adapter.