Structural · DWG NO. 010

Adapter

Wrap an incompatible interface so it matches the shape your code already expects.

TypeStructural
ScopeSingle object
ComplexityLow
Common inThird-party SDKs, legacy code, API version bridges

The library you need speaks a different shape

Your code calls `logger.log(message)` everywhere. A new metrics library you want to plug in as a logger only exposes `.record(eventName, payload)`. Rewriting either side isn't realistic — one is your whole codebase, the other is a third-party package.

A thin translator in between

The adapter implements the interface your code expects, and internally calls the library's real methods, translating arguments and return values as needed. Neither side is aware the other exists.

Client.log(msg)MetricsAdapter.record()MetricsLib(3rd party)

Adapting a metrics client into the app's logger shape

Every other part of the app keeps calling `logger.log(...)` — only the adapter knows the underlying library exists.

metrics-adapter.js
// Third-party library — its shape can't be changed.
const MetricsLib = {
  record(eventName, payload) {
    console.log(`[metrics] ${eventName}:`, payload);
  },
};

// The interface the rest of the app already expects.
class LoggerAdapter {
  constructor(metricsClient) { this.metricsClient = metricsClient; }

  log(message, level = "info") {
    this.metricsClient.record("log_event", { level, message });
  }
}

function runApp(logger) {
  logger.log("Server started");
  logger.log("Disk usage high", "warn");
}

runApp(new LoggerAdapter(MetricsLib));

Trade-offs