structural

Adapter

Allow incompatible interfaces to work together without changing the consuming code.

Problem

structural

A client needs to talk to a legacy class or external service whose interface does not match the rest of the codebase.

Integration notes

Adapters are useful when exposing a stable boundary over a legacy API, vendor SDK, or payload format mismatch.

Tradeoffs

  • Adds an extra layer of indirection.
  • Can hide useful vendor-specific capabilities if overused.
  • Keeps integration code isolated from core domain logic.

Languages

typescript, java, python, go, csharp, dotnet, react, angular, react-native

Platforms

applications, apis, service layers, integrations

Variants

frontend

API normalizer

react

Convert mismatched third-party payloads into a consistent UI-friendly shape.

Intent: Keep UI code clean when data sources disagree.

Problem: Components should not know vendor-specific field names or response quirks.

Solution: Use an adapter layer to return one consistent model to the UI.

Dependencies

adapter

Related variants

adapter-payment-wrapperadapter-event-translator

Examples

adapter

Useful for task boards, dashboards, and data-rich React apps.

Scenarios

Event payload mapper

An adapter converts incoming event payloads into the normalized analytics event shape used by the system.

Context: An event pipeline receives messages from several producer systems with different field names and formats.

Problem: Downstream processors should not need per-source conditionals for every incoming payload type.

Solution: Use Adapter to translate each source payload into one canonical event format.

backend

Language examples

Core languages

Frameworks and libraries

Typescripttypescript
TypeScript
type DomainEvent = {
  id: string;
  type: string;
  occurredAt: Date;
  payload: Record<string, unknown>;
};

type ExternalEvent = {
  event_id: string;
  event_type: string;
  created_at: string;
  data: Record<string, unknown>;
};

class EventAdapter {
  static fromExternal(
    event: ExternalEvent,
  ): DomainEvent {
    return {
      id: event.event_id,
      type: event.event_type,
      occurredAt: new Date(event.created_at),
      payload: event.data,
    };
  }
}

class EventProcessor {
  process(event: DomainEvent): void {
    console.log(
      `Processing ${event.type} event ${event.id}`,
    );
  }
}

const externalEvent: ExternalEvent = {
  event_id: "evt_123",
  event_type: "task.completed",
  created_at: "2026-08-05T20:00:00.000Z",
  data: {
    task_id: "task_456",
    completed_by: "user_789",
  },
};

const domainEvent =
  EventAdapter.fromExternal(externalEvent);

new EventProcessor().process(domainEvent);

Real-world examples

  • Legacy payment wrapper: Translate a provider's old charge API into the app's checkout service interface.
  • Third-party API normalization: Map inconsistent vendor payloads into one internal model before they reach the UI.
  • Analytics event translation: Convert several producer-specific event shapes into one canonical analytics schema.

Catalog record

Converts one interface into another interface that a client expects.

StructuralTypeScript

Catalog scenarios