We use the Adapter design pattern (also known as Wrapper) when working with a component that has an unstable interface or it's interface isn't compatible with our application. It allows wrapping the component with our interface and therefore completely hides the original interface from the application.
Most of you, for sure, develop your applications using the component architecture with third-party solutions (or your custom components from previous projects). Imagine that we want (or even need) to use a component which interface is being changed by its authors all the time. We use this component in 100 locations in our program and need to refactor the code in many places every time a new version pops up. A similar problem occurs when we already use some interface in our application and want to connect the component through this interface. It simply doesn't fit.
The Adapter design pattern wraps the component with our interface, so the application is completely shielded from the original component's interface. Whenever this interface changes, we just update our adapter. Thanks to the adapter, we can even change the component to another one easily in case we just don't like it anymore. In that case, we'd only change the adapter again, and the whole program won't even change at all.
The pattern is a kind of a mediator between our interface and the interface of a component which is unknown to the application. We can achieve this connection at the object or class level. The pattern therefore has 2 variants.
Client is a part of our system that calls our interface.
Adaptee is a component whose interface is unstable, incompatible,
or we just don't want our applications to depend on it. Our interface is defined
Adapter class, which transforms the methods from
Adapter can only serve
as a mediator and just call differently named methods. Or it may contain a
simple logic. As an example, we can imagine calling the
Insert(table, array) method which gets translated into calling
DatabaseQuery('INSERT INTO table VALUES value1, value2 ...'). The
array has been transformed into a single parameter and passed to
We can see that
Adaptee are connected
We can improve the pattern by adding an abstract
Adapter now inherits from the abstract
class. The purpose of the abstract class is so we could replace the adapter with
another one easily and be sure that we have maintained compatibility.
Target can also be just an interface.
Class Adapter is the less-used variant because it relies on the fact that the
Adaptee class can be inherited. The resulting adapter is a class
Adapter. Of course,
Target will be an interface so that multiple inheritance is
possible. We also lose the possibility to work with the
children, which we could do with Object Adapter (because the children provide
the same interface as the parent). But the advantage is that we can override
Wrappers are often built over databases (we can then change the database without a single change in our application) or over web services that often have complex APIs.