Design Pattern: Facade Pattern in Java

Facade pattern is used to hide the complexity of underlying subsystems. A new layer is created as Facade, which works as an entry point for the client.

This article demonstrates Facade pattern implementations in Java. Check the following examples.

Examples

Here are some examples of Facade pattern implementation in Java-

Example #1: Travel Plan

Let’s consider an example of a system used to plan travel. To go from one point to another we consider a few things –

  • Actual route – we use some map application
  • Expenses – we check how much the travel on the road will cost and if any extra fees like tolls are involved.
  • Weather info – to get an idea if we need to take any precautions while traveling
  • Car – as a mode of transport

So in this system, we are using classes for Map, Weather, Car, and Toll. This system is designed around these four classes.

As an implementation, if some client(class) wanted to use these classes, then it needs to be fully aware of these four classes and all implementation details.

We want to make it simple for the client(class). We will create a new class TravelFacade and implement all required functionality (using classes Map, Weather, Car, and Toll).

Then the client(class) will interact with/use the TravelFacade class only. (will not interact with Map, Weather, Car, or Toll directly)

Class Diagram

Take a look at the class diagram.

Map, Car, Toll, and Weather classes are subsystems. TravelFacade is the facade class, that unites subsystem classes. And the Point class is a utility class, used to represent the coordinates of a point, it is not directly related to Facade implementation.

Car Class [subsystem class]

// Car.java
// All function implementations are dummy implementations, just to demonstrate Facade

package com.bigboxcode.facade.transport;

import java.util.Random;

public class Car {

    public void startEngine() {
        System.out.println("Start Engine");
    }

    public void stopEngine() {
        System.out.println("Stop Engine");
    }

    public void goStraight() {
        System.out.println("Go Straight: ↑");
    }

    public void goLeft() {
        System.out.println("Go Left: ←");
    }

    public void goRight() {
        System.out.println("Go Right: →");
    }

    public double getDistanceTravelled() {
        Random r = new Random();
        return (r.nextInt((int)((10000-100)*10+1))+100*10) / 10.0;
    }
}

Map Class [subsystem class]

// Map.java
// All function implementations are dummy implementations, just to demonstrate Facade

package com.bigboxcode.facade.transport;

import java.util.Random;

public class Map {

    private double startLat;
    private double startLng;

    private double endLat;
    private double endLng;

    // define constructor
    public Map(double startLat, double startLng, double endLat, double endLng) {
        this.startLat = startLat;
        this.startLng = startLng;
        this.endLat = endLat;
        this.endLng = endLng;
    }

    public Point getCurrentLocation() {
        Random r = new Random();
        double currentLat = (r.nextInt((int)((90-(-90))*10+1))-90*10) / 10.0;
        double currentLng = (r.nextInt((int)((180-(-180))*10+1))-180*10) / 10.0;

        return new Point(currentLat, currentLng);
    }

    public String getNextMove() {
        Random rand = new Random();
        String[] nextMoves = {"straight", "left", "right"};

        return nextMoves[rand.nextInt(nextMoves.length)];
    }

    public Point[] getFullRoute() {
        Point[] points = new Point[10];
        Random r = new Random();

        for (int i = 0; i < 10; i++) {
            Point tempPoint = new Point(
                    (r.nextInt((int) ((90 - (-90)) * 10 + 1)) - 90 * 10) / 10.0,
                        (r.nextInt((int) ((180 - (-180)) * 10 + 1)) - 180 * 10) / 10.0
            );

            points[i] = tempPoint;
        }

        return points;
    }

    public void getLocationDetails(double lat, double lng) {
        System.out.println("Country: ABC");
        System.out.println("City: DEF");
        System.out.println("State: GHI");
        System.out.println("Zip: 101010");
    }
    
    public static class Point {
        private double lat;
        private double lng;
        
        public Point(double lat, double lng) {
            this.lat = lat;
            this.lng = lng;
        }

        public double getLat() {
            return lat;
        }

        public double getLng() {
            return lng;
        }
    }
}

Toll Class [subsystem class]

// Toll.java
// All function implementations are dummy implementations, just to demonstrate Facade

package com.bigboxcode.facade.transport;

import java.util.Random;

public class Toll {
    public Map.Point[] getTollPoints(double lat, double lng) {
        Map.Point[] points = new Map.Point[100];
        Random r = new Random();

        for (int i = 0; i < 3; i++) {
            Map.Point tempPoint = new Map.Point(
                    (r.nextInt((int) ((90 - (-90)) * 10 + 1)) - 90 * 10) / 10.0,
                    (r.nextInt((int) ((180 - (-180)) * 10 + 1)) - 180 * 10) / 10.0
            );

            points[i] = tempPoint;
        }

        return points;
    }

    public double getTollAmount(int tollPointId) {
        Random r = new Random();
        return (r.nextInt((int) ((100 - 1) * 10 + 1)) + 10) / 10.0;
    }

    public double getTotalToll(double lat, double lng) {
        Random r = new Random();
        return (r.nextInt((int) ((100 - 1) * 10 + 1)) + 10) / 10.0;
    }
}

Weather Class [subsystem class]

// Weather.java
// All function implementations are dummy implementations, just to demonstrate Facade

package com.bigboxcode.facade.transport;

public class Weather {

    public void getWeatherInfo(double lat, double lng) {
        System.out.println("Temperature: 20.7");
        System.out.println("Precipitation: 1%");
        System.out.println("Humidity: 73%");
        System.out.println("Wind: 8 km/h");
    }
}

Facade Class

TravelFacde initiates the objects of Map, Car, Weather, and Toll in the constructer, and uses those objects later where required. It also implements all functionality required by the client.

// TravelFacade.java
// All function implementations are dummy implementations, just to demonstrate Facade

package com.bigboxcode.facade.transport;

public class TravelFacade {
    double startLat;
    double startLng;

    double endLat;
    double endLng;

    Map map;
    Toll toll;
    Car car;
    Weather weather;

    // define constructor
    public TravelFacade(double startLat, double startLng, double endLat, double endLng) {
        this.startLat = startLat;
        this.startLng = startLng;
        this.endLat = endLat;
        this.endLng = endLng;

        // Initialize classes
        map = new Map(startLat, startLng, endLat, endLng);
        car = new Car();
        toll = new Toll();
        weather = new Weather();
    }

    public Map.Point[] getRoute() {
        return map.getFullRoute();
    }

    public void getLocationInfo(double lat, double lng) {
        map.getLocationDetails(lat, lng);
        weather.getWeatherInfo(lat, lng);
    }

    public Map.Point getCurrentLocation() {
        return map.getCurrentLocation();
    }

    public void operateCar() {
        Map.Point[] fullRoute = map.getFullRoute();

        car.startEngine();

        for (Map.Point point: fullRoute) {
            String nextMove = map.getNextMove();

            if (nextMove.equals("straight")) {
                car.goStraight();
            } else if (nextMove.equals("left")) {
                car.goLeft();
            } else if (nextMove.equals("right")) {
                car.goRight();
            }
        }

        car.stopEngine();
    }

    public void getTotalTollAmount(double lat, double lng) {
        System.out.println("Total Toll Amount: " + toll.getTotalToll(lat, lng));
    }

}

Demo

To use the Facade we just need to create a new object of the Facade class and use the implemented functions as required. No subsystem classes will be used directly at any point of the usage.

// Main.java
// All function implementations are dummy implementations, just to demonstrate Facade

package com.bigboxcode.facade.transport;

public class Main {
    public static void main(String[] args) {
        TravelFacade travelFacade = new TravelFacade(10, 10, 20, 30);

        Map.Point currentLocation = travelFacade.getCurrentLocation();

        System.out.println("Current Latitude: " + currentLocation.getLat());
        System.out.println("Current Longitude: " + currentLocation.getLng());

        System.out.println("-------------------------------------------");

        travelFacade.getLocationInfo(20, 30);

        System.out.println("-------------------------------------------");

        travelFacade.getTotalTollAmount(20, 30);

        System.out.println("-------------------------------------------");

        travelFacade.operateCar();
    }
}

Output

Current Latitude: -49.4
Current Longitude: 126.9
-------------------------------------------
Country: ABC
City: DEF
State: GHI
Zip: 101010
Temperature: 20.7
Precipitation: 1%
Humidity: 73%
Wind: 8 km/h
-------------------------------------------
Total Toll Amount: 80.6
-------------------------------------------
Start Engine
Go Right: →
Go Right: →
Go Right: →
Go Right: →
Go Right: →
Go Left: ←
Go Left: ←
Go Right: →
Go Right: →
Go Straight: ↑
Stop Engine

Source Code

Use the following link to get the source code:

Other Code Implementations

Use the following links to check Facade pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.