design patterns · medium

Adapter Pattern

Adapter is a structural GoF pattern that converts the interface of an existing class (the Adaptee — a third-party SDK or legacy module) into the interface a client expects (the Target), like a power-plug converter. The preferred object-adapter form implements the Target interface and holds a reference to the Adaptee, translating each Target call into the Adaptee's API (composition over inheritance). The client depends only on the Target, so it never knows the Adaptee exists — you can present several different backends through one interface by writing an adapter per backend. Benefits: decoupling from external interfaces (dependency inversion), isolating change to the adapter when an external API shifts, and testability (mock the Target). Cost: one extra wrapper class per adapted type. Distinct from Facade (which simplifies a whole subsystem) and Decorator (which adds behavior while keeping the same interface).

🔑 Key line

Adapter (structural): convert an existing class's interface into the one the client expects — a plug converter. Object adapter (preferred): implement the Target interface and HOLD the Adaptee, translating each call (composition). Decouples the client from third-party/legacy APIs, isolates change, and is testable. Differs from Facade (simplifies a subsystem) and Decorator (adds behavior, same interface).

The code

// Adapter — make an incompatible interface usable by the client.
// Target: what the client expects.
struct Logger {
virtual void log(const std::string&) = 0;
virtual ~Logger() = default;
};
// Adaptee: a useful class with the WRONG interface (3rd-party, legacy).
struct SpdLog {
void write(int level, const char* msg);
};
// Object adapter — HOLDS the adaptee, implements the target.
class SpdLogAdapter : public Logger {
SpdLog& impl_; // composition, not inheritance
public:
explicit SpdLogAdapter(SpdLog& s) : impl_(s) {}
void log(const std::string& m) override {
impl_.write(/*INFO*/ 1, m.c_str()); // translate the call
}
};
void app(Logger& log) {
log.log("hello");
} // client knows only Logger

What this lesson walks through

  1. 01Intent — a plug converter between interfaces
  2. 02Object adapter — composition (preferred)
  3. 03It translates the call across the gap
  4. 04Gotcha — Adapter vs Decorator vs Facade

An Adapter makes two incompatible interfaces work together — like a travel plug converter. The client expects a Target interface; the existing Adaptee offers a different one. The adapter sits between, presenting Target and translating to Adaptee.

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of Adapter Pattern and 100+ animated C++ interview lessons.

← Previous
GoF Decorator — Runtime Behaviour Composition Without Subclassing
Next →
Facade Pattern