Adapter Pattern

Let’s take some real time requirement to understand this pattern


John is a developer working for a client on weather forecasting application and he gets weather details from some third-party system say “X”, he has implemented all the code to consume weather details from “X” system and code is working fine, obviously John is very happy and clients too.

Adapter_pattern-No-Adapter_1

Suddenly one day Client requests John to change the third-party system from “X” to “Y”.

Note : Hope you understand that client will always come with the change whenever they feel.


Now John checks his code, he could find that lot of classes are using “X” system objects in his code and “Y” system objects are not compatible with his code.

Adapter_pattern-No-Adapter_2

If he starts changing all the classes wherever “X” system objects are used, it becomes like he is going to change lot of classes which are already tested, proven and working fine in Production.

What John has to do now to accommodate client’s requirement of using “Y” system without doing much of a change in his code?

This is where Adapter pattern comes to rescue him.

Note : Both the system “X” and “Y” produces same functionality but using different methods.


John knows that objects of “Y” system produces same functionality what “X” system produces.

Let’s understand few details about Adapter pattern before implementing it


Adapter pattern is one of the structural design patterns.

It is mainly used to communicate between 2 incompatible interfaces.
The object that is used to make these incompatible interfaces communicate each other is called as “Adapter”
Adapter lets incompatible interfaces work together that couldn’t otherwise because of incompatibility.

In real world, we can see some electronic adapters like
power supply adapters which will be used when we have incompatible plugs like 2 pins and 3 pins connectors.
Memory card adapter to plug the memory card from one device to another device.

So, adapter always acts as a bridge between incompatible interfaces.

Adapter_pattern-class_diagram

The classes/objects participating in adapter pattern


Target – defines the domain-specific interface that Client uses.
Adaptee – defines an existing interface that needs to be adapted.
Adapter – adapts the interface Adaptee to the Target interface.
Clientcollaborates with objects conforming to the Target interface.

Let’s implement the solution to the new modification request from John’s client


Solution to his problem without changing much of his code is Adapter pattern.

As we know adapter pattern acts as a bridge between 2 incompatible interfaces.

Solution can be represented as below

Adapter_pattern-with_adapter

We can see that 2 incompatible systems are connected through Adapter in the above diagram.

Let’s implement the pattern


We can implement the adapter pattern in 2 ways

1) Using Object Adapter – we use composition to achieve this
2) Using Class Adapter – we use inheritance to achieve this.

The best approach to implement this pattern is using Object Adapter and hence will implement the same in this article.

Step 1

Currently our code is using “X” weather system and interface for the same is as below

  1. package com.kb.adapter;
  2.  
  3. public interface XWeather {
  4.    
  5.     public String getWeatherInfo(String city);
  6.  
  7. }
package com.kb.adapter;

public interface XWeather {
	
	public String getWeatherInfo(String city);

}


It contains a method which provides the whether details based on City

Step 2

The following class defines the implementation to the XWeather interface .

  1. package com.kb.adapter;
  2. package com.kb.adapter;
  3.  
  4. public class XWeatherImpl implements XWeather {
  5.  
  6.     @Override
  7.     public String getWeatherInfo(String city) {
  8.         if ("Bangalore".equalsIgnoreCase(city)) {
  9.             return "weather info from X system -> 34 degree and light rain possible";
  10.         } else if ("Newyork".equalsIgnoreCase(city)) {
  11.             return "weather info from X system -> 20 degree and heavy rain possible";
  12.         } else {
  13.             return "Sorry weather forecasting not available for given city-> " + city;
  14.         }
  15.  
  16.     }
  17.  
  18. }
package com.kb.adapter;
package com.kb.adapter;

public class XWeatherImpl implements XWeather {

	@Override
	public String getWeatherInfo(String city) {
		if ("Bangalore".equalsIgnoreCase(city)) {
			return "weather info from X system -> 34 degree and light rain possible";
		} else if ("Newyork".equalsIgnoreCase(city)) {
			return "weather info from X system -> 20 degree and heavy rain possible";
		} else {
			return "Sorry weather forecasting not available for given city-> " + city;
		}

	}

}

Step 3

Let’s create 2 classes which uses “XWeather” API

Note : In real time, there could be 100 of  such classes which might be using XWeather API.


  1. package com.kb.adapter;
  2.  
  3. public class WeatherUser1 {
  4.    
  5.     XWeather weather;
  6.    
  7.     public WeatherUser1(XWeather weather) {
  8.         this.weather=weather;
  9.     }
  10.    
  11.     public void getWeather(String city){
  12.         String weatherInfo = weather.getWeatherInfo(city);
  13.         System.out.println("User 1 -> "+weatherInfo);
  14.        
  15.     }
  16. }
package com.kb.adapter;

public class WeatherUser1 {
	
	XWeather weather;
	
	public WeatherUser1(XWeather weather) {
		this.weather=weather;
	}
	
	public void getWeather(String city){
		String weatherInfo = weather.getWeatherInfo(city);
		System.out.println("User 1 -> "+weatherInfo);
		
	}
}

  1. package com.kb.adapter;
  2.  
  3. public class WeatherUser2 {
  4.    
  5.     XWeather weather;
  6.    
  7.     public WeatherUser2(XWeather weather) {
  8.         this.weather=weather;
  9.     }
  10.    
  11.    
  12.     public void getWeather(String city){
  13.         String weatherInfo = weather.getWeatherInfo(city);
  14.         System.out.println("User 2 -> "+weatherInfo);
  15.        
  16.     }
  17. }
package com.kb.adapter;

public class WeatherUser2 {
	
	XWeather weather;
	
	public WeatherUser2(XWeather weather) {
		this.weather=weather;
	}
	
	
	public void getWeather(String city){
		String weatherInfo = weather.getWeatherInfo(city);
		System.out.println("User 2 -> "+weatherInfo);
		
	}
}

Step 4

Create a client test class to use these Weather classes

  1. package com.kb.adapter;
  2.  
  3. public class AdapterClient {
  4.     public static void main(String[] args) {
  5.        
  6.         //old code using "X" weather system
  7.        
  8.         System.out.println("Old \"X\" weather system output.....");
  9.         XWeather weatherX = new XWeatherImpl();
  10.         WeatherUser1 weatherUser1 = new WeatherUser1(weatherX);
  11.         weatherUser1.getWeather("Newyork");
  12.         WeatherUser2 weatherUser2 = new WeatherUser2(weatherX);
  13.         weatherUser2.getWeather("Bangalore");
  14.     }
  15.  
  16. }
package com.kb.adapter;

public class AdapterClient {
	public static void main(String[] args) {
		
		//old code using "X" weather system
		
		System.out.println("Old \"X\" weather system output.....");
		XWeather weatherX = new XWeatherImpl();
		WeatherUser1 weatherUser1 = new WeatherUser1(weatherX);
		weatherUser1.getWeather("Newyork");
		WeatherUser2 weatherUser2 = new WeatherUser2(weatherX);
		weatherUser2.getWeather("Bangalore");
	}

}


We don’t have any issues till this as our code is using weather system “X”

Now client demands to use “Y” weather system instead of “X” weather system
This is where our adapter comes to rescue us.

Step 5

New weather system “Y” interface looks like below

  1. package com.kb.adapter;
  2.  
  3. public interface YWeather {
  4.    
  5.     public String getWeatherDetails(String city);
  6.  
  7. }
package com.kb.adapter;

public interface YWeather {
	
	public String getWeatherDetails(String city);

}

Step 6

Implementation for the above interface looks as below

  1. package com.kb.adapter;
  2.  
  3. public class YWeatherImpl implements YWeather {
  4.  
  5.     @Override
  6.     public String getWeatherDetails(String city) {
  7.         if ("Bangalore".equalsIgnoreCase(city)) {
  8.             return "weather info from Y system -> 40 degree and light rain possible";
  9.         } else if ("Newyork".equalsIgnoreCase(city)) {
  10.             return "weather info from Y system -> 25 degree and heavy rain possible";
  11.         } else {
  12.             return "Sorry weather forecasting not available for given city-> " + city;
  13.         }
  14.  
  15.     }
  16.  
  17. }
package com.kb.adapter;

public class YWeatherImpl implements YWeather {

	@Override
	public String getWeatherDetails(String city) {
		if ("Bangalore".equalsIgnoreCase(city)) {
			return "weather info from Y system -> 40 degree and light rain possible";
		} else if ("Newyork".equalsIgnoreCase(city)) {
			return "weather info from Y system -> 25 degree and heavy rain possible";
		} else {
			return "Sorry weather forecasting not available for given city-> " + city;
		}

	}

}


As you can see, this “Y” system has a different method which need to be used in the code but most of the code is already using “X” weather system API, it’s really hard and risky to change the entire set of classes using it.

We need some way, that’s able to fulfil the client’s new requirement of using “Y” weather system and also, we should make less (or) no change in the current code.
This can be achieved by using Adapter pattern.

We will create an adapter which implements “XWeather”, and it wraps an “YWeather” object (the type it supposes to be adapted).

Step 7

Create the adapter class as below

  1. package com.kb.adapter;
  2.  
  3. public class XToYWeatherAdapter implements XWeather {
  4.     YWeather yWeather;
  5.    
  6.     public XToYWeatherAdapter(YWeather yWeather) {
  7.         this.yWeather = yWeather;
  8.     }
  9.    
  10.     @Override
  11.     public String getWeatherInfo(String city) {
  12.         return yWeather.getWeatherDetails(city);
  13.     }
  14.  
  15. }
package com.kb.adapter;

public class XToYWeatherAdapter implements XWeather {
	YWeather yWeather;
	
	public XToYWeatherAdapter(YWeather yWeather) {
		this.yWeather = yWeather;
	}
	
	@Override
	public String getWeatherInfo(String city) {
		return yWeather.getWeatherDetails(city);
	}

}


In the above code, we have created an adapter which wraps or adapts the “Y” weather system using composition.

Step 8

Let us test the above code and see whether it can solve the Client’s problem.

  1. package com.kb.adapter;
  2.  
  3. public class AdapterClient {
  4.     public static void main(String[] args) {
  5.        
  6.         //old code using "X" weather system
  7.        
  8.         System.out.println("Old \"X\" weather system output.....");
  9.         XWeather weatherX = new XWeatherImpl();
  10.         WeatherUser1 weatherUser1 = new WeatherUser1(weatherX);
  11.         weatherUser1.getWeather("Newyork");
  12.         WeatherUser2 weatherUser2 = new WeatherUser2(weatherX);
  13.         weatherUser2.getWeather("Bangalore");
  14.        
  15.         //Changing old code to use "Y" weather system
  16.         //Only minimal change is required and no need to change in any other class except here
  17.         System.out.println("New \"Y\" weather system output.....");
  18.         YWeather WeatherY = new YWeatherImpl();
  19.         XWeather weatherXToY = new XToYWeatherAdapter(WeatherY);
  20.        
  21.         WeatherUser1 weatherUser3 = new WeatherUser1(weatherXToY);
  22.         weatherUser3.getWeather("Newyork");
  23.         WeatherUser2 weatherUser4 = new WeatherUser2(weatherXToY);
  24.         weatherUser4.getWeather("Bangalore");
  25.     }
  26.  
  27. }
package com.kb.adapter;

public class AdapterClient {
	public static void main(String[] args) {
		
		//old code using "X" weather system
		
		System.out.println("Old \"X\" weather system output.....");
		XWeather weatherX = new XWeatherImpl();
		WeatherUser1 weatherUser1 = new WeatherUser1(weatherX);
		weatherUser1.getWeather("Newyork");
		WeatherUser2 weatherUser2 = new WeatherUser2(weatherX);
		weatherUser2.getWeather("Bangalore");
		
		//Changing old code to use "Y" weather system
		//Only minimal change is required and no need to change in any other class except here
		System.out.println("New \"Y\" weather system output.....");
		YWeather WeatherY = new YWeatherImpl();
		XWeather weatherXToY = new XToYWeatherAdapter(WeatherY);
		
		WeatherUser1 weatherUser3 = new WeatherUser1(weatherXToY);
		weatherUser3.getWeather("Newyork");
		WeatherUser2 weatherUser4 = new WeatherUser2(weatherXToY);
		weatherUser4.getWeather("Bangalore");
	}

}



When to use this pattern ?


When there is an existing class which we need to use but its interface does not match as per our need
When we want to create a reusable class that collaborates unrelated or incompatible classes, that is, classes that don’t necessarily have compatible interfaces.

About the Author

Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on