← All Patterns
structural4 participants

Adapter

Convert the interface of a class into another interface that clients expect. Adapter lets classes work together that could not otherwise because of incompatible interfaces.

The Problem

You have a useful class (legacy C simulator) but its interface is incompatible with what the rest of your system expects (modern C++ Simulator interface). You cannot modify the legacy code — it is third-party, generated, or too risky to change.

Structure

Clientrun(Simulator&)«interface»Simulatorstart() step() stop()LegacySimAdapterdelegatesLegacySimulatorinit_sim(argc,argv)step_sim() → intclose_sim()Client only sees Simulator& — legacy C API hidden behind adapter

Execution Walkthrough

1

Target interface

Define the interface your system expects: Simulator with start(), step(), stop().

2

Adaptee exists

3

Adapter wraps

4

Translation

5

Client unaware

Code Comparison

Client must know about both interfaces and do the translation itself — duplicated across every call site.

// BAD: client does translation manually everywhere
void run_simulation(LegacySimulator& legacy) {
  legacy.init_sim(0, nullptr);  // remember: argc/argv
  while (legacy.step_sim() == 0) {}  // remember: 0 = ok
  legacy.close_sim();
  // Any new caller must repeat this translation.
  // Change LegacySimulator API? Update every call site.
}

// And modern code cannot use it polymorphically:
void run(Simulator& sim);  // expects modern interface
LegacySimulator ls;
run(ls);  // compile error — wrong type

Full C++ Implementation

C++ · Adapter
#include <iostream>

struct Simulator {
  virtual void start() = 0;
  virtual bool step()  = 0;
  virtual void stop()  = 0;
  virtual ~Simulator() = default;
};

struct LegacySimulator {
  int ticks_ = 0;
  void init_sim(int, char**) {
    ticks_ = 0;
    std::cout << "[legacy] init\n";
  }
  int step_sim() {
    if (ticks_++ < 3) {
      std::cout << "[legacy] tick " << ticks_ << "\n";
      return 0;   // 0 = continue
    }
    return -1;    // -1 = done
  }
  void close_sim() { std::cout << "[legacy] close\n"; }
};

struct LegacySimAdapter : Simulator {
  LegacySimulator& l_;
  explicit LegacySimAdapter(LegacySimulator& l) : l_(l) {}

  void start() override { l_.init_sim(0, nullptr); }
  bool step()  override { return l_.step_sim() == 0; }
  void stop()  override { l_.close_sim(); }
};

void run(Simulator& sim) {
  sim.start();
  while (sim.step()) {}
  sim.stop();
}

int main() {
  LegacySimulator   legacy;
  LegacySimAdapter  adapter{legacy};
  run(adapter);
}

Participants

TargetAdapterAdapteeClient

Where it is used

C++ STL

std::stack/std::queue adapt std::deque to LIFO/FIFO interfaces.

Hardware abstraction

A HAL adapter wraps a vendor FPGA SDK behind a uniform register-mapped interface.

Legacy EDA

A Tcl API adapter wraps a C simulation engine for modern C++ tooling to call uniformly.

Third-party SDKs

libcurl C API wrapped behind a modern C++ RAII interface with futures and std::error_code.

DecoratorFacade