Adapter
- Is a Structural Design Pattern
- Also known as wrapper pattern
- An adapter allows incompatible interfaces to work together
- It converts one interface into another that the client expects
| Role | Meaning |
|---|---|
| Client | Existing code that expects some interface |
| Target | The interface the client expects |
| Adaptee | Existing / new / legacy class with incompatible interface |
| Adapter | The translator between Target and Adaptee |
| ### Class Adapter vs. Object Adapter |
This is a frequent interview question. The main difference lies in how they talk to the Adaptee:
- Class Adapter (Inheritance): Uses Is-A relationship. It can only adapt a specific class, but it can override the Adaptee's behavior since it's a subclass.
interface Target {
void operation();
}
class Adaptee {
public void specificRequest() {
System.out.println("Specific Request");
}
}
class Adapter implements Target extends Adaptee {
@Override
void operation() {
specificRequest();
}
}
class Client {
Adapter adapter = new Adapter();
adapter.operation();
}
- Object Adapter (Composition): Uses Has-A relationship. It holds an instance of the Adaptee inside it. This is generally preferred in modern SE (like Java) because it's more flexible and follows the "favor composition over inheritance" principle.
Object Adaptor (Composition-based)
Adapterhas an instance ofadapteeAdapterdelegates toadapteeinstance
interface Target {
void request();
}
class Adaptee {
public void specificRequest() {
System.out.println("Specific Request");
}
}
class ObjectAdapter implements Target {
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new ObjectAdapter(adaptee);
target.request();
}
}
