Adapter is a structural design pattern that allows objects with incompatible interfaces to collaborate.
Problem: an existing component offers functionality, but is not compatible with
the new system being developed
Solution: the adapter pattern connects incompatible components
- Allows the reuse of existing components
- Converts the interface of the existing component into another interface expected by the calling component
- Useful in interface engineering projects and in reengineering projects
- Often used to provide a new interface for a legacy system
→ Also called wrapper


An adapter wraps one of the objects to hide the complexity of conversion happening behind the scenes. The wrapped object isn’t even aware of the adapter.

Definition: legacy system
- An old system that continues to be used, even though newer technology or more efficient methods are now available
- Evolved over a long time
- Still actively used in a production environment
- Often designed without modern software design methodologies → High maintenance cost
- Considered irreplaceable because a re-implementation is too expensive or impossible
Problems with legacy systems
- Reasons for the continued use of a legacy system
- System cost: the system still makes money, but the cost of designing a new system
with the same functionality is too high
- Poor engineering (or poor management): the system is hard to change because
the compiler is no longer available or source code has been lost
- Availability: the system requires 100% availability and cannot simply be taken out of
service and replaced with a new system
- Pragmatism: the system is installed and working
- But: change is required due to new functional-, nonfunctional- or pseudo
requirements
Comparison: adapter pattern vs. bridge pattern
- Similarities
- Both hide the details of the underlying implementation
- Differences
- Adapter: designed towards making unrelated components work together
- Applied to systems that are already designed (reengineering, interface engineering projects)
- Inheritance → delegation
- Bridge: used up-front in a design to let abstractions and implementations vary independently
- Greenfield engineering of an “extensible system”
- New “beasts” can be added to the “zoo” (“application and solution domain zoo”), even if these are not known at analysis or system design time
- Delegation → inheritance

public class ThermoAdapter implements ThermoInterface {
private FahrenheitThermo thermo;
public ThermoAdapter() {
thermo = new FahrenheitThermo();
}
public double getTempC() {
return (thermo.getFahrenheitTemperature() - 32.0) * (5.0 / 9.0);
}
}
Structure

- 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
This implementation uses inheritance: the adapter inherits interfaces from both objects at the same time. Note that this approach can only be implemented in programming languages that support multiple inheritance.

The Class Adapter doesn’t need to wrap any objects because it inherits behaviors from both the client and the service. The adaptation happens within the overridden methods. The resulting adapter can be used in place of an existing client class.
<aside>
Applicability
- Use the Adapter class when you want to use some existing class, but its interface isn’t compatible with the rest of your code.
- Use the pattern when you want to reuse several existing subclasses that lack some common functionality that can’t be added to the superclass.
</aside>
TEXT
<aside>
How to Implement
- Make sure that you have at least two classes with incompatible interfaces
- A useful service class, which you can’t change (often 3rd-party, legacy or with lots of existing dependencies).
- One or several client classes that would benefit from using the service class.
- Declare the client interface and describe how clients communicate with the service.
- Create the adapter class and make it follow the client interface. Leave all the methods empty for now.
- Add a field to the adapter class to store a reference to the service object. The common practice is to initialize this field via the constructor, but sometimes it’s more convenient to pass it to the adapter when calling its methods.
- One by one, implement all methods of the client interface in the adapter class. The adapter should delegate most of the real work to the service object, handling only the interface or data format conversion.
- Clients should use the adapter via the client interface. This will let you change or extend the adapters without affecting the client code.”
</aside>