What is Adapter Pattern?
Adapter pattern is a structural pattern that converts the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
When to use it?
- Use Adapter pattern when you want to use legacy code or third-party libraries but its interface is incompatible with other part of your application.
Problem
We've been using an old printer but now new free software is invented which is integrated with modern printer. The problem is we can't afford to buy modern printer but still want to use the software. Is there a way of using new software but with old printer which is incompatible with the software? Yes, here Adapter pattern comes in handy.
Solution
NewSoftware
This is our Client. This only acceptsModernPrinter
interface. NewSoftware thinks it's dealing withModernPrinter
.ModernPrinter
Provides compatible interface for Client.PrinterAdapter
Receives a method callmodernPrint()
fromModernPrinter
, then translates it into a format theOldPrinter
This is what we want to use but its interface is incompatible with ourNewSoftware
.oldPrint()
gets executed whenModernPrinter
callsmodernPrint()
.
Structure
Remember an adapter can be used with any subclass of the adaptee.
Implementation in Java
public class OldPrinter {
public void oldPrint(String document) {
System.out.println(document + " by old printer");
}
}
public interface ModernPrinter {
void modernPrint(String document);
}
public class PrinterAdapter implements ModernPrinter {
private OldPrinter oldPrinter;
public PrinterAdapter(OldPrinter oldPrinter) {
this.oldPrinter = oldPrinter;
}
@Override
public void modernPrint(String document) {
oldPrinter.oldPrint(document);
}
}
public class NewSoftware {
public static void main(String[] args) {
OldPrinter oldPrinter = new OldPrinter();
// Because PrinterAdapter implements ModernPrinter, it can be seen
// as a ModernPrinter which is integrated with NewSoftware
ModernPrinter adapter = new PrinterAdapter(oldPrinter);
adapter.modernPrint("Hello world");
}
}
In our assumption, you NewSoftware
is integrated with ModernPrinter
, so it doesn't make sense to code like oldPrinter.oldPrint("Hello world");
in NewSoftware
class (even though it will be compiled without errors).
Output:
Hello world by old printer
Pitfalls
- An adapter that does a lot of work besides simple interface translation results in adding/altering adaptee behavior, which is far from the intent of Adapter pattern.
Object and Class Adapter
What we’ve seen is called an Object Adapter, which adapts the adaptee using composition. There is another type of adapter called a Class Adapter, which uses inheritance to achieve the intent of the Adapter pattern.
Java doesn't support multiple inheritance. So we can't use class adapter in Java, but we will study it anyway as you might encounter class adapter in other language.
Because object adapter uses composition, Adapter
can hold references to one or more Adaptee
objects. Thus, object adapter offers more flexibility. While class adapter is tightly coupled with one and only one adaptee which leads to less flexibility.
You can check all the design pattern implementations here.
GitHub Repository
Top comments (0)