Skip to main content

Adapter

Overview

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

When to use

  • You need to integrate a legacy or third-party API.
  • You want to reuse existing classes without modifying them.

Java example

class LegacyLogger {
void write(String msg) { /* ... */ }
}

interface Logger {
void log(String msg);
}

class LegacyLoggerAdapter implements Logger {
private final LegacyLogger legacy;
LegacyLoggerAdapter(LegacyLogger legacy) { this.legacy = legacy; }
public void log(String msg) { legacy.write(msg); }
}

TypeScript example

class LegacyLogger {
write(msg: string): void {}
}

interface Logger {
log(msg: string): void;
}

class LegacyLoggerAdapter implements Logger {
constructor(private legacy: LegacyLogger) {}
log(msg: string): void {
this.legacy.write(msg);
}
}

Pros and cons

Pros:

  • Enables reuse without changing original code.
  • Keeps client code stable.

Cons:

  • Adds an extra abstraction layer.
  • Too many adapters can complicate the codebase.

Common pitfalls

  • Over-adapting when a simpler wrapper works.
  • Hiding breaking behavior differences.