Adapter Pattern
- Reading time
- 2 min read
- Word count
- 222 words
- Diagram count
- 0 diagrams
Source: Victor Bona's Obsidian Compendium snapshot, Knowledge base/Design Patterns/Adapter Pattern.md.
Adapter allows classes with incompatible interfaces to work together by converting the interface of one class into an interface expected by the client. It acts as a wrapper that sits between two unrelated components, translating calls so that they can collaborate.
- Intent: “Adapter is a structural design pattern that allows objects with incompatible interfaces to collaborate.” In other words, it converts the interface of one class into another interface that the client expects.
- Use Cases: Integration of legacy code with new code (e.g., wrapping an old API so a new system can use it), using a class that doesn’t match a required interface, or adapting one library’s interface to another’s. For example, if your code expects a
ILoggerinterface but you want to use a third-party logging classExternalLoggerwith a different method, you can write an Adapter that implementsILoggerand delegates toExternalLoggerinternally.
Example: Adapting a third-party audio player to your application’s media player interface:
// Existing interface in our system:
interface MediaPlayer {
play(fileName: string): void;
}
// A third-party class with a different interface:
class ThirdPartyAudioPlayer {
playFile(file: string, codec: string): void {
console.log(`Playing ${file} with codec ${codec}`);
}
}
// Adapter class to make ThirdPartyAudioPlayer conform to MediaPlayer:
class AudioPlayerAdapter implements MediaPlayer {
private adaptee: ThirdPartyAudioPlayer;
constructor(adaptee: ThirdPartyAudioPlayer) {
this.adaptee = adaptee;
}
play(fileName: string): void {
// The adapter translates the simple play() call into the expected format:
const codec = fileName.endsWith(".mp3") ? "MP3" : "default";
this.adaptee.playFile(fileName, codec);
}
}
// Client code uses MediaPlayer interface:
const player: MediaPlayer = new AudioPlayerAdapter(new ThirdPartyAudioPlayer());
player.play("song.mp3"); // The ThirdPartyAudioPlayer is used under the hood
Here, AudioPlayerAdapter implements the MediaPlayer interface expected by our app, but internally it holds a ThirdPartyAudioPlayer and calls its playFile method with appropriate parameters. The client code doesn’t need to know about the third-party specifics – it just uses the standard interface. The Adapter pattern promotes reusability by allowing existing incompatible classes to work with new systems without modifying their source.