The adapter pattern is definitely one of the most used design patterns in software development. As per GOF guys, Adapter pattern is defined as the following: “Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.”
Well let’s translate, It means that Adapter pattern links two incompatible interfaces which have the same functionality but their methods are called a little differently. Sometimes it is also called a wrapper.
It can be used in the following situations:
- Say you have a class – Class A – with a dependency on some interface type. On the other hand you have another class – Class B – that would be ideal to inject into Class A as the dependency, but Class B does not implement the necessary interface.
- Factor out some tightly coupled dependency. A common scenario would be a direct usage of some .NET class, say HttpRuntime in a method that you want to test. You must have a valid HttpRuntime while running the test otherwise the test may fail and that is of course not acceptable. The solution is to let the method be dependent on some abstraction that is injected to it – the question is how to extract HttpRuntime and make it implement some interface instead? The solution is to write an adapter that sits between Class A and Class B that wraps Class B’s functionality
The classes/objects participating in adapter pattern:
- 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.
Suppose we have a system that works with different types of engines (normal, economic, etc) that share common characteristics as well as their operation, it is desired to link to the system an electric engine type with a different operation than the others, New class without this affecting the initial logic of the application.
Since we consider linking a new engine totally different to the rest of the engines defined in the system, then we deduce that although it is an engine cannot have a treatment equal to that of others, since the way to turn it on, put it into operation and up Turning it off could be very different and could affect the established logic, as we cannot abruptly modify our code then we will use the Adapter pattern to solve our problem.
Class Normal Engine
This class represents the structure of the normal engines with which the system works, basically implements IEngine interface and perform the basic operation that it provides.
Class ElectricEngineAdapter (Adapter)
it establishes the bridge by means of which the incompatible class can be used, implements IEngine Interface, it makes the communication with the class to adapt using for this an instance of the same.
Interface IElectricObject (Adaptee) and class Electric Engine
As we see despite being a engine has very different characteristics to the other types of engines of the system, therefore cannot implements directly IEngine, instead it is accessed by the Adapter class.
As we saw, it was possible to use a new class without affecting the logic of the system, we used a class that served as a bridge or adapter for the new class, without affecting the code of our existing classes.
The example was very basic, however many times we will have to use libraries or classes that cannot be modified and must be done in the least traumatic way for our application, therefore this pattern can be very helpful in discriminating the use of these new classes by means of an adapter.
Thanks for reading.