Easy Tutorial
❮ Proxy Pattern Singleton Pattern ❯

Adapter Pattern

The Adapter Pattern (Adapter Pattern) acts as a bridge between two incompatible interfaces. This type of design pattern is a structural pattern that combines the functionalities of two separate interfaces.

This pattern involves a single class which is responsible for joining functionalities of independent or incompatible interfaces. A real-life example is the card reader which acts as an adapter between memory card and a laptop. You plug the memory card into the card reader and the card reader into the laptop so that the memory card can be read via the laptop.

We will demonstrate the use of the Adapter Pattern with the following example: an audio player device that can only play mp3 files, using a more advanced audio player to play vlc and mp4 files.

Introduction

Intent: Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

Main Problem: Often the existing objects in a software system need to be placed in new environments, but the new environment's interface requirements are not met by the existing objects.

When to Use: 1. The system needs to use existing classes, and their interfaces do not match the system's requirements.

  1. To create a reusable class that works with unrelated or unforeseen classes, including those that may be introduced in the future, which do not necessarily have consistent interfaces.
  2. To convert the interface of a class into another interface through interface conversion.

How to Solve: Inheritance or dependency (preferably).

Key Code: The adapter inherits or depends on existing objects to implement the desired target interface.

Examples: 1. US electrical 110V to Chinese 220V using an adapter.

  1. JAVA JDK 1.1 provided the Enumeration interface, while JDK 1.2 introduced the Iterator interface. To use JDK 1.2, the old system's Enumeration interface needs to be converted to the Iterator interface, requiring the Adapter Pattern.
  2. Running WINDOWS programs on LINUX.
  3. JDBC in JAVA.

Advantages: 1. Allows any two unrelated classes to work together.

  1. Increases class reusability.
  2. Enhances class transparency.
  3. Offers flexibility.

Disadvantages: 1. Overuse of adapters can make the system messy and difficult to grasp. For example, seeing a call to interface A, but internally it's adapted to interface B's implementation.

  1. Since JAVA only allows single inheritance, it can only adapt one adapter class at most, and the target class must be abstract.

Usage Scenarios: When there is a need to modify the interface of a normally running system, consider using the Adapter Pattern.

Notes: Adapters are not added during detailed design but are used to solve problems in operational projects.

Implementation

We have a MediaPlayer interface and a concrete class AudioPlayer that implements the MediaPlayer interface. By default, AudioPlayer can play mp3 format audio files.

We also have another interface AdvancedMediaPlayer and concrete classes implementing this interface. These classes can play vlc and mp4 format files.

We want AudioPlayer to play other formats as well. To achieve this, we create an adapter class MediaAdapter that implements the MediaPlayer interface and uses AdvancedMediaPlayer objects to play the required format.

AudioPlayer uses the adapter class MediaAdapter to pass the desired audio type without knowing the actual classes that can play the desired format. The AdapterPatternDemo class uses the AudioPlayer class to play various formats.

Step 1

Create interfaces for media player and advanced media player.

MediaPlayer.java

public interface MediaPlayer {
   public void play(String audioType, String fileName);
}

AdvancedMediaPlayer.java

public interface AdvancedMediaPlayer { 
   public void playVlc(String fileName);
   public void playMp4(String fileName);
}

Step 2

Create concrete classes implementing the AdvancedMediaPlayer interface.

VlcPlayer.java

public class VlcPlayer implements AdvancedMediaPlayer{
   @Override
   public void playVlc(String fileName) {
      System.out.println("Playing vlc file. Name: "+ fileName);      
   }

   @Override
   public void playMp4(String fileName) {
      // Do nothing
   }
}

Mp4Player.java

public class Mp4Player implements AdvancedMediaPlayer{

   @Override
   public void playVlc(String fileName) {
      // Do nothing
   }

   @Override
   public void playMp4(String fileName) {
      System.out.println("Playing mp4 file. Name: "+ fileName);      
   }
}

Step 3

Create an adapter class implementing the MediaPlayer interface.

MediaAdapter.java

public class MediaAdapter implements MediaPlayer {

   AdvancedMediaPlayer advancedMusicPlayer;

   public MediaAdapter(String audioType){
      if(audioType.equalsIgnoreCase("vlc") ){
         advancedMusicPlayer = new VlcPlayer();       
      } else if (audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer = new Mp4Player();
      }  
   }

   @Override
   public void play(String audioType, String fileName) {
      if(audioType.equalsIgnoreCase("vlc")){
         advancedMusicPlayer.playVlc(fileName);
      }else if(audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer.playMp4(fileName);
      }
   }
}

Step 4

Create a concrete class implementing the MediaPlayer interface.

AudioPlayer.java

public class AudioPlayer implements MediaPlayer {
   MediaAdapter mediaAdapter; 

   @Override
   public void play(String audioType, String fileName) {    

      // Inbuilt support to play mp3 music files
      if(audioType.equalsIgnoreCase("mp3")){
         System.out.println("Playing mp3 file. Name: "+ fileName);         
      } 
      // mediaAdapter is providing support to play other file formats
      else if(audioType.equalsIgnoreCase("vlc") 
         || audioType.equalsIgnoreCase("mp4")){
         mediaAdapter = new MediaAdapter(audioType);
         mediaAdapter.play(audioType, fileName);
      }
      else{
         System.out.println("Invalid media. "+
            audioType + " format not supported");
      }
   }   
}

Step 5

Use the AudioPlayer to play different types of audio formats.

AdapterPatternDemo.java

public class AdapterPatternDemo {
   public static void main(String[] args) {
      AudioPlayer audioPlayer = new AudioPlayer();

      audioPlayer.play("mp3", "beyond the horizon.mp3");
      audioPlayer.play("mp4", "alone.mp4");
      audioPlayer.play("vlc", "far far away.vlc");
      audioPlayer.play("avi", "mind me.avi");
   }
}

Step 6

Execute the program, output results:

Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported
❮ Proxy Pattern Singleton Pattern ❯