Adapter Design Pattern
Posted on August 26, 2025 • 5 minutes • 1004 words
In software development, we often face situations where we need to integrate existing code with new code. However, the interfaces may not always match. Instead of rewriting existing code, we can use the Adapter Design Pattern to bridge the gap.
The Adapter Pattern acts as a bridge between two incompatible interfaces. It allows a class with a specific interface to be used with another class expecting a different interface.

Real-Life Analogy
Think of a power adapter. If you travel to a country where the power socket is different, you don’t throw away your charger. Instead, you use a power adapter to fit your charger into the new socket.
Similarly, in programming, we use adapters when we want to reuse an existing class with an incompatible interface.
Example: Media Player
Suppose we have an old media player that can only play MP3 files. Now, we introduce a new advanced player that can play multiple formats like MP4, VLC, and MKV.
We want to integrate both without changing the old code.
Without Adapter (The Problem)
#include <iostream>
#include <string>
using namespace std;
class OldMediaPlayer {
public:
void playMP3(string fileName) {
cout << "Playing MP3 file: " << fileName << endl;
}
};
class AdvancedMediaPlayer {
public:
void playMP4(string fileName) {
cout << "Playing MP4 file: " << fileName << endl;
}
void playVLC(string fileName) {
cout << "Playing VLC file: " << fileName << endl;
}
};
int main() {
OldMediaPlayer oldPlayer;
AdvancedMediaPlayer newPlayer;
string audioType = "vlc";
string fileName = "movie.vlc";
if (audioType == "mp3") {
oldPlayer.playMP3(fileName);
} else if (audioType == "mp4") {
newPlayer.playMP4(fileName);
} else if (audioType == "vlc") {
newPlayer.playVLC(fileName);
} else {
cout << "Invalid media type" << endl;
}
return 0;
}
Problem
- Every time a new format is added, we must update the client code (
main()
). - The client is directly dependent on multiple player classes.
- Violates Open-Closed Principle (OCP) because client code changes frequently.
With Adapter (The Solution)
We introduce an Adapter that translates requests from the old interface (MediaPlayer
) to the new interface (AdvancedMediaPlayer
).
#include <iostream>
#include <string>
using namespace std;
// Target Interface
class MediaPlayer {
public:
virtual void play(string audioType, string fileName) = 0;
};
// Adaptee 1 - Old player
class OldMediaPlayer {
public:
void playMP3(string fileName) {
cout << "Playing MP3 file: " << fileName << endl;
}
};
// Adaptee 2 - Advanced player
class AdvancedMediaPlayer {
public:
void playMP4(string fileName) {
cout << "Playing MP4 file: " << fileName << endl;
}
void playVLC(string fileName) {
cout << "Playing VLC file: " << fileName << endl;
}
};
// Adapter
class MediaAdapter : public MediaPlayer {
AdvancedMediaPlayer advancedPlayer;
OldMediaPlayer oldPlayer;
public:
void play(string audioType, string fileName) override {
if (audioType == "mp3") {
oldPlayer.playMP3(fileName);
} else if (audioType == "mp4") {
advancedPlayer.playMP4(fileName);
} else if (audioType == "vlc") {
advancedPlayer.playVLC(fileName);
} else {
cout << "Invalid media type" << endl;
}
}
};
// Client
int main() {
MediaPlayer* player = new MediaAdapter();
player->play("mp3", "song.mp3");
player->play("mp4", "video.mp4");
player->play("vlc", "movie.vlc");
delete player;
return 0;
}
Advantages of Using Adapter Pattern
- Reusability – We reuse existing
OldMediaPlayer
andAdvancedMediaPlayer
without modifying them. - Flexibility – The client (
main
) only depends onMediaPlayer
, not individual players. - Open-Closed Principle – Adding new formats requires minimal changes (extend Adapter, not client).
- Cleaner Code – Client code is simplified.
The Adapter Pattern is very useful when we want to integrate existing functionality with new features but their interfaces are incompatible. Instead of rewriting code, we create a wrapper (Adapter) that translates one interface into another.
In our Media Player example, the Adapter bridges the gap between old MP3-only functionality and the advanced multi-format player. This makes the system extensible, flexible, and easier to maintain.
Example in Youtube Video
VideoPlayer.h
#ifndef VIDEO_PLAYER_H
#define VIDEO_PLAYER_H
#include <iostream>
class VideoPlayer
{
public:
virtual void play(const std::string& videoType, const std::string& fileName) = 0;
virtual ~VideoPlayer() = default;
};
#endif
AdvancedVideoPlayer.h
#ifndef ADVANCED_VIDEO_PLAYER_H
#define ADVANCED_VIDEO_PLAYER_H
#include <iostream>
class AdvancedVideoPlayer
{
public:
virtual void playMov(const std::string& videoType, const std::string& fileName) = 0;
virtual void playMkv(const std::string& videoType, const std::string& fileName) = 0;
virtual ~AdvancedVideoPlayer() = default;
};
class mkvPlayer : public AdvancedVideoPlayer
{
public:
virtual void playMov(const std::string& videoType, const std::string& fileName)
{
//dummy
}
virtual void playMkv(const std::string& videoType, const std::string& fileName)
{
std::cout << "Playing mkv file: " << fileName << std::endl;
}
};
class movPlayer : public AdvancedVideoPlayer
{
public:
virtual void playMov(const std::string& videoType, const std::string& fileName)
{
std::cout << "Playing mov file: " << fileName << std::endl;
}
virtual void playMkv(const std::string& videoType, const std::string& fileName)
{
//dummy
}
};
#endif
Adapter.cpp
#include <iostream>
#include <memory>
#include "./lib/VideoPlayer.h"
#include "./lib/AdvancedVideoPlayer.h"
class VideoAdapter : public VideoPlayer
{
public:
virtual void play(const std::string& videoType, const std::string& fileName)
{
if(!_adavancedPlayerPtr)
return;
if(videoType == "mov")
{
_adavancedPlayerPtr->playMov(videoType,fileName);
}
else if(videoType == "mkv")
{
_adavancedPlayerPtr->playMkv(videoType,fileName);
}
}
VideoAdapter(const std::string& videoType)
{
if(videoType == "mov")
{
_adavancedPlayerPtr = std::make_unique<movPlayer>();
}
else if(videoType == "mkv")
{
_adavancedPlayerPtr = std::make_unique<mkvPlayer>();
}
}
private:
std::unique_ptr<AdvancedVideoPlayer> _adavancedPlayerPtr;
};
class CDPlayer : public VideoPlayer
{
public:
void play(const std::string& videoType, const std::string& fileName) override
{
if (videoType == "mp4")
{
std::cout << "Playing mp4 file: " << fileName << std::endl;
}
else if (videoType == "mov" || videoType == "mkv")
{
VideoAdapter adptr(videoType);
adptr.play(videoType,fileName);
}
else
{
std::cout << "Invalid media. " << videoType << " format not supported." << std::endl;
}
}
};
// Demo
int main()
{
CDPlayer player;
player.play("mp4", "video1.mp4");
player.play("mkv", "video2.mkv");
player.play("mov", "video3.mov");
player.play("flac", "video3.flac");
}