Adapter Design Pattern
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. (dofactory)
- Target defines the domain-specific interface that Client uses.
- Adapter adapts the interface Adaptee to the Target interface.
- Adaptee defines an existing interface that needs adapting.
- Client collaborates with objects conforming to the Target interface.
- Class Adapter
- Class Adapter implements Target interface and inherits from Adaptee, but Object Adapter inheriting a Target class/interface and aggregate the Adaptee. The design differences are primarily that overriding Adaptee behavior can be done more easily with a Class Adapter, whereas adding behavior to Adaptees can be done more easily with an object adapter.
- Two-Ways Adapter
- The Two-Ways Adapters are adapters that implements both interfaces of Target and Adaptee. The adapted object can be used as Target in new systems dealing with Target classes or as Adaptee in other systems dealing with Adaptee classes.
- Two-way adapters and n-way adapters are hard to implement in systems not supporting multiple inheritance. If adapter has to extend the Target class it can not extent another class like Adaptee, so the Adaptee should be an interface and all the calls should be delegated from the adapter to the Adaptee object.
- Pluggable Adapter
- A distinguishing feature of pluggable adapters is that the name of a method called by the client and that existing in the ITarget interface can be different. The adapter must be able to handle the name change. In the previous adapter variations, this was true for all Adaptee methods, but the client had to use the names in the ITarget interface.
- What characterizes a pluggable adapter is that it will have constructors for each of the types that it adapts. In each of them, it does the delegate assignments (one, or more than one if there are further methods for rerouting).
- When a class that you need to use does not meet the requirements of an interface.
- If another library has to be used only an adapter for the new library is required without having to change the application code.
- Used to adapt 3rd parties libraries and frameworks - most of the applications using third party libraries use adapters as a middle layer between the application and the 3rd party library to decouple the application from the library.
- Translates one interface for a class into a compatible interface.
- Wraps an existing class with a new interface
- Some say that the Adapter pattern is just a fix for a badly designed system, which did not consider all possibilities. While this is a fair point, it is an important part of a pluggable architecture.
Object Adapter Example
- Adapter makes things work after they are 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.
- Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.
- Adapter is meant to change the interface of an existing object. Decorator enhances another object without changing its interface. Decorator is thus more transparent to the application than an adapter is. As a consequence, Decorator supports recursive composition, which is not possible with pure Adapters.
- Facade defines a new interface, whereas Adapter reuses an old interface. Remember that Adapter makes two existing interfaces work together as opposed to defining an entirely new one.
- There are many cases when the adapter can play the role of the Strategy pattern. If we have several modules implementing the same functionality and we wrote adapters for them, the adapters are implementing the same interface. We can simply replace the adapters objects at run time because they implements the same interface.