Seth Barrett

Daily Blog Post: March 23rd, 2023

design1

Mar 23rd, 2023

Implementing the Adapter Pattern for Integrating Incompatible Interfaces

The Adapter Pattern is a structural design pattern that allows two incompatible interfaces to work together. It acts as a bridge between two interfaces, converting the interface of one class into another interface that the client expects. This pattern is also known as the Wrapper Pattern.

In software development, we often come across scenarios where we need to integrate two systems or components that have different interfaces. We can't change the interface of these systems, but we need them to work together. This is where the Adapter Pattern comes in handy.

Let's consider an example of a client application that needs to display weather information from different weather services. Each weather service has its own API and interface for retrieving weather information. To display the weather information on the client application, we need to create an adapter that can convert the different weather service interfaces into a common interface that the client expects.

To implement the Adapter Pattern, we need to create an adapter class that implements the interface that the client expects. The adapter class also needs to have a reference to the object that implements the incompatible interface. The adapter class then maps the methods of the client interface to the methods of the incompatible interface and calls them.

Here's an example code snippet that demonstrates the Adapter Pattern:

// Client interface
    interface WeatherService {
        public String[] getWeatherData();
    }
    
    // Incompatible interface
    class ThirdPartyWeatherService {
        public String[] getWeatherInfo() {
            // returns weather information in different format
        }
    }
    
    // Adapter class
    class ThirdPartyWeatherServiceAdapter implements WeatherService {
        private ThirdPartyWeatherService thirdPartyWeatherService;
        
        public ThirdPartyWeatherServiceAdapter(ThirdPartyWeatherService thirdPartyWeatherService) {
            this.thirdPartyWeatherService = thirdPartyWeatherService;
        }
        
        public String[] getWeatherData() {
            String[] weatherInfo = thirdPartyWeatherService.getWeatherInfo();
            // adapt the weather information to match the client interface
            return weatherInfo;
        }
    }
    
    // Client code
    public class Client {
        public static void main(String[] args) {
            ThirdPartyWeatherService thirdPartyWeatherService = new ThirdPartyWeatherService();
            WeatherService weatherService = new ThirdPartyWeatherServiceAdapter(thirdPartyWeatherService);
            
            // use the weather service through the adapter
            String[] weatherData = weatherService.getWeatherData();
            // display the weather information on the client application
        }
    }

In this example, we have a client interface WeatherService and an incompatible interface ThirdPartyWeatherService that returns weather information in a different format. We create an adapter class ThirdPartyWeatherServiceAdapter that implements the WeatherService interface and adapts the getWeatherData method to call the getWeatherInfo method of the ThirdPartyWeatherService class.

In the Client class, we create an instance of the ThirdPartyWeatherService class and pass it to the ThirdPartyWeatherServiceAdapter constructor. We then use the WeatherService interface to get the weather data from the ThirdPartyWeatherService object through the adapter.

In conclusion, the Adapter Pattern is a useful design pattern for integrating two systems or components that have incompatible interfaces. It acts as a bridge between the interfaces, converting the interface of one class into another interface that the client expects. By using this pattern, we can create a flexible and reusable solution for integrating different systems or components.