creational

Adapter

Convert the interface of a class into another interface that clients expect.

You have code that expects one interface, and a class that offers a different one. Both work fine. They just do not fit.

This happens constantly with third-party libraries and old systems. You cannot edit the library, and rewriting your own code to match it would spread that library's shape through your whole project.

Adapter is a small class that sits between them. It implements the interface your code expects, and translates each call into whatever the other class actually needs.

A power plug adapter — your device expects round pins; the wall has flat pins. The adapter bridges the gap.

Key Concepts

1
The adapter implements the interface your code already uses, so your code needs no changes at all.
2
Inside, it holds a reference to the class it is adapting. Each method converts the arguments, calls the real method, and converts the result back.
3
All the awkwardness lives in this one small class. If you later replace the library, you rewrite the adapter and nothing else.

When to use it

  • Integrating third-party libraries
  • Reusing legacy code in a new system
  • Making unrelated classes work together

Watch out for

  • Prefer Object Adapter (composition) over Class Adapter (inheritance) for flexibility.
java
public class LegacyAnalytics {
    public void trackEvent(String cat, String action, int val) { }
}
public interface Analytics {
    void logEvent(String name, Map<String, Object> props);
}
public class AnalyticsAdapter implements Analytics {
    private final LegacyAnalytics legacy;
    public AnalyticsAdapter(LegacyAnalytics l) { this.legacy = l; }
    public void logEvent(String name, Map<String, Object> props) {
        String cat = (String) props.getOrDefault("category", "general");
        int val = (int) props.getOrDefault("value", 0);
        legacy.trackEvent(cat, name, val);
    }
}