Adapter Design Pattern Real World Example in C#
Last Updated: 2023-12-25 01:16:36The Adapter Design Pattern is a structural design pattern. In this blog post, we will discuss the Adapter Pattern with a real-world example in C#. I will also give you the complete source code so that you can customize the code based on your requirements. I will use the C# language but you can use any object-oriented programming language to design the pattern.
You may already know what Adapter Design Patterns are, but here I will give you some short poring about the Adapter Design Pattern so that you can relate to our example easily.
Adapter Design Pattern in Shorts
- The Adapter Design Pattern is a structural design pattern.
- It works as a bridge between two inconsistent interfaces.
- A class that is responsible to join the functionalities of two inconsistent interfaces.
- It enables classes with incompatible interfaces to work together without modifying their source code.
When we can use the Adapter Design Pattern?
The adapter pattern is useful when we want to use a class that does not fit the design of your existing solution. We want to add new functionality to an existing project but the existing implementation is not matching with our new requirements.
A real-world example of an Adapter Design Pattern
You already know that the main purpose of the Adapter Design Pattern is joining the existing functionalities with the new functionalities. when
- We can't change the existing implementation.
- The existing implementation is not capable to reflect the new functionalities.
- But We need to reuse the existing features.
So, let's create a real-world example based on this scenario.
Let's consider that we have an Audio Player application, that can play only play Mp3 format's audio file. Now our new requirement is we need to implement a feature so that our Audio Player can play WAV(Waveform Audio) and AAC(Advance Audio Code) types of audio also.
Remember we can't make any changes to our existing interface. But we will reuse some functionalities.
Let's create our existing Audio Player first which can play only mp3 types of audio.
simply we will create an interface(MediaPlayer.cs) and a class(Mp3Player.cs) that will implement our interface(MediaPlayer.cs) . And then we will call the class from the main function.
MediaPlayer.cs interface. This is our existing interface which we can't modify to implement our new features.
public interface MediaPlayer
{
public void Play(String fileType, String fileName);
}
The Play method will take two parameters one is for checking the audio type and one is for the audio file we want to play.
The Mp3Player.cs class. Which implemented the MediaPlayer.cs interface and played only the mp3 audio file.
class Mp3Player : MediaPlayer
{
// we will reuse this function
public void Play(string fileType, string fileName)
{
if(fileType.ToUpper() == "MP3")
{
Console.WriteLine("Playing " +fileType +". " + fileName + "......");
}
else
{
Console.WriteLine("Invalid media format. " + fileType + " not supported!");
}
}
}
Now call the Mp3Player from the main function.
static void Main(string[] args)
{
Mp3Player mp3 = new Mp3Player();
mp3.Play("mp3","new mp3 song 1");
Mp3Player mp3 = new Mp3Player();
mp3.Play("mp3","new mp3 song 2");
Mp3Player mp3 = new Mp3Player();
mp3.Play("AAC","new AAC song 1");
Mp3Player mp3 = new Mp3Player();
mp3.Play("WAV","new WAV song 1");
}
Output
Playing mp3. new mp3 song 1......
Playing mp3. new mp3 song 2......
Invalid media format. AAC not supported!
Invalid media format. WAV not supported!
So, from the output, you can see that our Audio Player can play only the mp3 format's audio. And for the AAC and WAV it's showing that format is not supported. So, let's implement the Adapter Design Pattern so that our Audio Player can play AAC and WAV type's audio.
Adapter Design Pattern to an Existing Application.
We need to remember that we can't modify our existing interface (MediaPlayer.cs). So first of all create an interface for our new functionalities.
AdvancePlayer.cs. That is responsible for our new functionalities.
public interface AdvancePlayer
{
public void playWAV(string fileName);
public void playAAC(string fileName);
}
public class WAVPlayer : AdvancePlayer
{
public void playAAC(string fileName)
{
// do nothing
throw new NotImplementedException();
}
public void playWAV(string fileName)
{
Console.WriteLine("Playing WAV " + fileName + "......");
}
}
public class AACPlayer : AdvancePlayer
{
public void playAAC(string fileName)
{
Console.WriteLine("Playing ACC. " + fileName + "......");
}
public void playWAV(string fileName)
{
// do nothing
throw new NotImplementedException();
}
}
So, our new features are ready. Now we need an Adapter class that will join our new features with the existing feature. So, let's create an adapter class.
MediaAdapter.cs class. Which will join our new features with the existing feature
public class MediaAdapter : MediaPlayer
{
AdvancePlayer advanceMediaPlayer;
public MediaAdapter(string fileType)
{
// new feature
if(fileType.ToUpper() == "WVA")
{
advanceMediaPlayer = new WAVPlayer();
}else if (fileType.ToUpper() == "AAC")
{
advanceMediaPlayer = new AACPlayer();
}
}
// implemented the existing function
// reused existing function
public void Play(string fileType, string fileName)
{
if (fileType.ToUpper() == "WVA")
{
advanceMediaPlayer.playWAV(fileName);
}
else if (fileType.ToUpper() == "AAC")
{
advanceMediaPlayer.playAAC(fileName);
}
}
}
Here look carefully at the MediaAdapter class it implemented our existing Pay function and also created new functionalities for the WAV and AAC types of audio.
Now let's make some changes to the existing Mp3Player.cs class.
class Mp3Player : MediaPlayer
{
// for new feature
MediaAdapter mediaAdapter;
public void Play(string fileType, string fileName)
{
// old version
if(fileType.ToUpper() == "MP3")
{
Console.WriteLine("Playing " +fileType +". " + fileName + "......");
}else if(fileType.ToUpper() == "WAV" || fileType.ToUpper() == "AAC")
{ // new feature using adapter
mediaAdapter = new MediaAdapter(fileType);
mediaAdapter.Play(fileType, fileName);
}
else
{
Console.WriteLine("Invalid media format. " + fileType + " not supported!");
}
}
}
Remember we didn't change the interface but made some changes to the concrete class so that we can reuse the Pay function.
Now call our main function with the same input.
static void Main(string[] args)
{
Mp3Player mp3 = new Mp3Player();
mp3.Play("mp3","new mp3 song 1");
Mp3Player mp3 = new Mp3Player();
mp3.Play("mp3","new mp3 song 2");
Mp3Player mp3 = new Mp3Player();
mp3.Play("AAC","new AAC song 1");
Mp3Player mp3 = new Mp3Player();
mp3.Play("WAV","new WAV song 1");
}
This time output will be
Playing mp3. new mp3 song 1......
Playing mp3. new mp3 song 2......
Playing AAC. new AAC song 1......
Playing WAV. new WAV song 1......
So this time our audio player can play the AAC and WAV audio along with the mp3 type audio. So this is how an Adapter Class can join an existing feature the new feature without modifying the existing interface but reusing some functionalities.
Conclusion
Here we have discussed the Adapter Design Pattern with a real-world example. In the example, we have added a new feature to an existing application. We didn't make any changes to the existing interface but we reused some functionalities of its concrete class. Please note that this was a very simple example of the Adapter Desing Pattern.
Still you face problems, feel free to contact with me, I will try my best to help you.