Adapter Pattern
- is a structural design pattern that allows 2 existing incompatible interfaces to collaborate
Real-World Example
Memory Card Example
Consider that you have some pictures on your memory card and you need to transfer them to your computer. In order to transfer them, you need some kind of adapter that is compatible with your computer ports so that you can attach a memory card to your computer. In this case card reader is an adapter.
Power Adapter
Another example would be the famous power adapter; a three-legged plug can’t be connected to a two-pronged outlet, it needs to use a power adapter that makes it compatible with the two-pronged outlet. Yet another example would be a translator translating words spoken by one person to another
Problem (why Adapter is needed)
You have:
- a new interface your client expects
- you cannot change the legacy code
Types
Object Adapter - uses composition
Object Adapter - This implementation uses the object composition principle: the adapter implements the interface of one object and wraps the other one. It can be implemented in all popular programming languages
- The Client is a class that contains the existing business logic of the program.
- The Client Interface describes a protocol that other classes must follow to be able to collaborate with the client code.
- The Service is some useful class (usually 3rd-party or legacy). The client can’t use this class directly because it has an incompatible interface.
- The Adapter is a class that’s able to work with both the client and the service: it implements the client interface while wrapping the service object. The adapter receives calls from the client via the adapter interface and translates them into calls to the wrapped service object in a format it can understand.
- The client code doesn’t get coupled to the concrete adapter class as long as it works with the adapter via the client interface. Thanks to this, you can introduce new types of adapters into the program without breaking the existing client code. This can be useful when the interface of the service class gets changed or replaced: you can just create a new adapter class without changing the client code.
Class Adapter - uses inheritance
TODO
Code Example
Object Adapter Example
Target interface (what the client expects)
interface PaymentProcessor { void pay(double amount); }Adaptee (existing, incompatible, legacy, not allowed to be changed class)
class LegacyPaymentGateway { public void makePayment(int cents) { System.out.println("Paid " + cents + " cents using legacy gateway"); } }Adapter
class PaymentAdapter implements PaymentProcessor { private final LegacyPaymentGateway legacyGateway; public PaymentAdapter(LegacyPaymentGateway legacyGateway) { this.legacyGateway = legacyGateway; } @Override public void pay(double amount) { int cents = (int) (amount * 100); legacyGateway.makePayment(cents); } }Client code
public class Main { public static void main(String[] args) { PaymentProcessor processor = new PaymentAdapter(new LegacyPaymentGateway()); processor.pay(25.50); } }Client → PaymentProcessor → Adapter → LegacyPaymentGateway
Class Adapter Example
TODO
Comparisons
Click here to expand...
Link to originalAdapter Pattern vs Bridge Pattern:
- Bridge and Adapter both point at an existing type. But the bridge will point at an abstract type, and the adapter might point to a concrete type. The bridge will allow you to pair the implementation at runtime, whereas the adapter usually won’t
- Adapter makes things work after they’re designed; Bridge makes them work before they are.
- Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together
- Difference between Bridge pattern and Adapter pattern
- When do you use the Bridge Pattern? How is it different from Adapter pattern?
Link to originalAdapter Pattern vs Facade Pattern
- Facade defines a new interface, whereas Adapter uses an old interface. Remember that Adapter makes two existing interfaces work together as opposed to defining an entirely new one.
- Adapter and Facade are both wrappers, but they are different kinds of wrappers. The intent of Facade is to produce a simpler interface, and the intent of Adapter is to design an existing interface. While Facade routinely wraps multiple objects and Adapter wraps a single object; Facade could front-end a single complex object and Adapter could wrap several legacy objects
- Adapter and Facade both have a different interface than what they wrap. But the adapter derives from an existing interface, whereas the facade creates a new interface
Link to originalAdapter Pattern vs Decorator Pattern
- main difference is that:
- the decorator pattern is used to add functionality to an object at run-time without changing the object’s method signature(s)
- the adapter pattern is used to change the interface of an object to adapt it to another interface (i.e. different method signature(s))
- The decorator pattern is similar to the adapter pattern in that one service “wraps” another. However, in contrast to adapters, decorators expose the same service as what they’re decorating.
Link to originalAdapter Pattern vs Proxy Pattern:
- intent: adapter makes an incompatible interface compatible, proxy controls access, add behavior, or delay creation
- who initiates: in adapter, client uses adapter to speak to old legacy code, in proxy client uses proxy as real object
- transparency: in adapter client knows, in proxy client may not know
/structural-design-patterns/wrapper-patterns/adapter-pattern/structure-object-adapter-indexed-2x.png)