Adapter Pattern

What is it?
Why Use It?
- You want to reuse a class that doesn’t match your interface.
- You want to connect a new system to an old one without changing either.
- You can’t modify a 3rd-party or legacy class.
Real-World Analogy
TypeScript Example — Round Hole & Square Pegs
Ts
// Target interface: expects round pegs
class RoundHole {
constructor(private radius: number) {}
fits(peg: RoundPeg): boolean {
return this.radius >= peg.getRadius();
}
}
// Expected object
class RoundPeg {
constructor(private radius: number) {}
getRadius(): number {
return this.radius;
}
}
// Incompatible class
class SquarePeg {
constructor(private width: number) {}
getWidth(): number {
return this.width;
}
}
// Adapter: makes SquarePeg look like RoundPeg
class SquarePegAdapter extends RoundPeg {
constructor(private squarePeg: SquarePeg) {
super(0); // dummy value; we override getRadius
}
getRadius(): number {
// Fits a square peg into the smallest circle that can contain it
return (this.squarePeg.getWidth() * Math.sqrt(2)) / 2;
}
}
// Client code
const hole = new RoundHole(5);
const roundPeg = new RoundPeg(5);
console.log("Round peg fits:", hole.fits(roundPeg)); // true
const smallSquarePeg = new SquarePeg(5);
const largeSquarePeg = new SquarePeg(10);
const smallAdapter = new SquarePegAdapter(smallSquarePeg);
const largeAdapter = new SquarePegAdapter(largeSquarePeg);
console.log("Small square peg fits:", hole.fits(smallAdapter)); // true
console.log("Large square peg fits:", hole.fits(largeAdapter)); // false
What’s Happening?
- RoundHole expects RoundPeg.
- SquarePeg is incompatible.
- We wrap SquarePeg in SquarePegAdapter to mimic a RoundPeg.
- The adapter handles conversion logic (getRadius()).
When to Use Adapter
- You want to integrate incompatible systems (e.g., XML to JSON).
- You’re working with legacy code or third-party APIs.
- You want to avoid rewriting or duplicating business logic.
Pros & Cons
- Respects Open/Closed Principle: extend behavior without changing existing code.
- Enables reuse of existing classes.
- Keeps code modular and decoupled.
- Adds extra classes and boilerplate.
- Sometimes easier to just refactor the old code if possible.