when do we need Adapter pattern?
Existing Interface
interface Shape {
public int calculateArea(int r);
}
Current Implementation for Shape interface
class Square implements Shape {
@Override
public int calculateArea(int r) {
return r * r;
}
}
Now Consider that you want Circle class to adapt to our existing interface which in no way we can modify (Written by third party).
class Circle {
public double calculateCircularArea (int r) {
return 3.14 * r * r;
}
}
Now we have adapt Circle implementation to our Shape interface. So we need an adaptor as they are incompatible.
class CircleAdaptor extends Circle implements Shape {
@Override
public int calculateArea(int r) {
return (int) calculateCircularArea(r);
}
}
CircleAdaptor - Is the Adaptor for Circle;
Circle - Is the Adaptee;
Shape - Is the Target Interface.
public class AdapterPattern {
public static void main(String[] args) {
Shape circle = new CirCleAdaptor();
System.out.println("Circle Area " + circle.calculateArea(5));
Shape square = new Square();
System.out.println("Square Area " + square.calculateArea(5));
}
}
Hope this gives a better idea about when to use it.
See also what is Decorator pattern?
I worked on a system which needed to interface with external DVRs. For the most part, all DVRs have the same basic functionality: start recording from a certain video source; stop recording; start playback from a certain time; stop playback, etc.
Every DVR manufacturer provided a software library, allowing us to write code to control their device (for sake of this discussion, I'll refer to it as the SDK). Even though every SDK provided APIs for all the basic functionality, none of them were quite the same. Here's a very rough example, but you get the idea:
- BeginPlayback(DateTime startTime);
- StartPlayback(long startTimeTicks);
- Playback(string startDate, string startTime);
Our software needed to be able to interact with all DVRs. So instead of writing horrible switch/cases for each different SDK, we created our own common IDVRController interface, and wrote all of our system code to that interface:
- Playback(DateTime startTime);
We then wrote a different adapter implementation for each SDK, all of which implemented our IDVRController interface. We used a config file to specify the type of DVR the system would connect to, and a Factory pattern to instantiate the correct implementer of IDVRController for that DVR.
In that way, the adapter pattern made our system code simpler: we always coded to IDVRController. And it allowed us to roll out adapters for new SDKs post-deployment (our Factory used reflection to instantiate the correct IDVRController instance).