Friday, 1 December 2017

Design Patterns - Adapter

The adapter design pattern is about creating a layer where  two different components can work together, just like a real life adapter you use it to connect things that couldn't work together otherwise, following is a story to help you understand what is this about. 

You are a software engineer in SoftCorp , after several months of trials and other challenges you and your team are almost done working on an innovative GPS software for self driving cars, the release date is close and all are happy...

 The problem :

Suddenly your manager is calling you at her office and wants to change the weather api!

The software is using the WeatherPoint api to get weather updates so your software can make calculations for long distance trips, your manager wants to change the api to a different vendor : WeatherOracle.


The Solution:


Of course one option is to completely refactor your code base of thousands lines of code to use the new api , or you can use the easy way of the adapter pattern and be the hero of the day!


Project : SelfDrivingCarGPS

get the code

Before we dive in to the specifics of the pattern lets take a moment to explain in a high level what we are going to do:
Our CarGPS currently is expecting a WeatherPoint class but we need to use a WeatherOracle instead.

The adapter solution is to create a class WeatherPointToOracleAdapter where we will wrap a WeatherOracle obj adapting it to a WeatherPoint so the rest of your software does not need to know about the change!

here there is a simplified UML about the adapter pattern:



The first step is to create our adapter, the WeatherPointToOracleAdapter class :
 we will  place it in the adapter package.

public class WeatherPointToOracleAdapter implements WeatherPoint {

    private WeatherOracle weatherOracle;

    public WeatherPointToOracleAdapter(WeatherOracle weatherOracle){
        this.weatherOracle = weatherOracle;
    }

     
    @Override 
    public String getWeather(String location) {
        // we use the weather oracle method to get weather 
       return weatherOracle.getWeatherData(location);
    }

 
    @Override     
   public String getLocation() {
        // we use the weather oracle method to get location 
       return weatherOracle.getTheLocation();
    }
}

Take a look in our adapter:
  • Implements the WeatherPoint interface because we will adapt the given object to a WeatherPoint
  • has a field WeatherOracle 
  • takes a WeatherOracle obj in the constructor , this object will be adapted !

we can use it like this:

public class Demo {
    public static void main(String[] args) {
        // Our new api
     WeatherOracleApi weatherOracle = new WeatherOracleApi("London");
        // adapting the api from WeatherOracle to WeatherPoint 
     WeatherPoint adaptedApi = new WeatherPointToOracleAdapter(weatherOracle);
        // using our class with no changes! 
     CarGPS carGPS = new CarGPS(adaptedApi,adaptedApi.getLocation());

 
     carGPS.getWeatherData();
 
     carGPS.planTrip();
    }
}

Our CarGPS has no knowledge that we have placed an adapter or that the api is changed and just works like before using our new api!

Now our implementation looks like :


Well done , with your new skills you have saved your colleagues many hours of trivial work!
Explore the code and try to build your own adapters!

Happy coding!



No comments:

Post a Comment