On this page
Adapter
The Adapter pattern converts the interface of a class into another interface that clients expect — allowing incompatible classes to work together.
Problem
You need to use an existing class, but its interface does not match what your code expects.
Solution
// Target interface your code expects
interface PaymentProcessor {
void pay(double amount);
}
// Adaptee — existing incompatible class
class LegacyPaymentGateway {
public void makePayment(String currency, int cents) {
System.out.println("Paid " + cents + " " + currency);
}
}
// Adapter
class LegacyPaymentAdapter implements PaymentProcessor {
private final LegacyPaymentGateway gateway;
LegacyPaymentAdapter(LegacyPaymentGateway gateway) {
this.gateway = gateway;
}
@Override
public void pay(double amount) {
gateway.makePayment("USD", (int) (amount * 100));
}
}
// Client
PaymentProcessor processor = new LegacyPaymentAdapter(new LegacyPaymentGateway());
processor.pay(49.99);
Object Adapter vs Class Adapter
| Object Adapter | Class Adapter |
|---|---|
| Uses composition | Uses inheritance |
| More flexible | Cannot adapt subclasses |
| Preferred in Java | Limited by single inheritance |
Java Examples
// Arrays.asList adapts array to List interface
List<String> list = Arrays.asList(array);
// InputStreamReader adapts bytes to characters
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
// Spring MVC HandlerAdapter adapts various controller types
When to Use
- Integrate third-party libraries with incompatible interfaces
- Wrap legacy code for new systems
- Create reusable classes that cooperate with unrelated classes
Best Practices
- Use object adapter (composition) in Java
- Keep the adapter thin — only translate interfaces, do not add business logic
- Consider whether a facade (simpler interface) is more appropriate
- In modern code, lambda wrappers can serve as simple adapters