When do we need to go for Adapter pattern? If possible give me a real world example that suits that 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.
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:
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:
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).
In computer programming, the adapter pattern (often referred to as the wrapper pattern or simply a wrapper) is a design pattern that translates one interface for a class into a compatible interface. An adapter allows classes to work together that normally could not because of incompatible interfaces, by providing its interface to clients while using the original interface. The adapter translates calls to its interface into calls to the original interface, and the amount of code necessary to do this is typically small. The adapter is also responsible for transforming data into appropriate forms. For instance, if multiple boolean values are stored as a single integer but your consumer requires a 'true'/'false', the adapter would be responsible for extracting the appropriate values from the integer value.
Wikipedia!!!
You can use the Adapter design pattern when you have to deal with different interfaces with similar behavior (which usually means classes with similar behavior but with different methods). An example of it would be a class to connect to a Samsung TV and another one to connect to a Sony TV. They will share common behavior like open menu, start playback, connect to a network and etc but each library will have a different implementation of it (with different method names and signatures). These different vendor specific implementations are called Adaptee in the UML diagrams.
So, in your code (called Client in the UML diagrams), instead of hard code the method calls of each vendor (or Adaptee), you could then create a generic interface (called Target in UML diagrams) to wrap these similar behaviors and work with only one type of object.
The Adapters will then implement the Target interface delegating its method calls to the Adaptees that are passed to the Adapters via constructor.
For you to realize this in Java code, I wrote a very simple project using exactly the same example mentioned above using adapters to deal with multiple smart TV interfaces. The code is small, well documented and self explanatory so dig on it to see how a real world implementation would look like.
Just download the code and import it to Eclipse (or your favorite IDE) as a Maven project. You can execute the code by running org.example.Main.java. Remember that the important thing here is to understand how classes and interfaces are assembled together to design the pattern. I also created some fake Adaptees in the package com.thirdparty.libs. Hope it helps!
https://github.com/Dannemann/java-design-patterns
A very common example of the adapter pattern is done through the Service Provider Interface and is commonly used in a lot of the Java EE framework.
The reason for it is to allow different implementations of Java EE but programmers simply code to the Java EE spec rather than something implementation specific.
As opposed to something like coding directly using WebSphere classes which lock you into using WebSphere.
Or worse (from my experience), Apache HTTP Client and find out later that because you coded to that implementation rather than the normal HttpUrlConnection you have to do a lot of recoding because it does not support the current version of TLS which would've been avoided if the original developer coded to a more stable API and we just need to upgrade Java runtime.
Adapter pattern is required in following scenario:
Say you have defined an interface I1
with method M1
and M2
C1
and C2
implements this interface I1
, now for C1
while implementing M1
and M2
you have found no help from other existing classes so you need to write all logic by yourself.
Now while implementing class C2
you have come across class C3
with methods M3
and M4
that can be used to implement M1
and M2
for C2
so to utilize those M3
and M4
in class C2
you extends class C3
and use M3
and M4
of C3
.
In this example C2
becomes Adapter class
and C3
becomes adaptee
package com.design.patterns;
public class AdapterExample {
public static void main(String[] args) {
Shape line = new LineShape();
line.draw();
Shape text = new TextShape();
text.draw();
}
}
//==Start from here
interface Shape{
public void draw();
}
class LineShape implements Shape{
@Override
public void draw() {
System.out.println("write some logic and draw line");
}
}
//Adapter
class TextShape extends TextView implements Shape{
@Override
public void draw() {
System.out.println("logic is already there in class TextView");
drawText();
}
}
// Adaptee
class TextView{
public void drawText() {
System.out.println("Drawing Text Shape");
}
}