Facade Design Pattern

The Facade design pattern simplifies the complexity of a system through a simpler interface.

It improves access to our system by allowing other systems or subsystems to use a common access point that reduces complexity, minimizing interactions and dependencies.

This design pattern is very useful because it also decouples systems.

Facade

What are the parts of the Facade design pattern

We said that the design pattern Facade has a simple interface and accessible to other systems or subsystems.
This simplifies complexity for external service clients by exposing a clearer interface and unified access to these features, making them easier to use.

We have then in this pattern three parts:

  • The Client who accesses the facade.
  • The Facade that accesses the other functionalities and unifies or simplifies them.
  • The rest of functionalities / subsystems, which are “behind” the facade.

Facade

How to create the Facade design pattern

We talked before that the objective of the Facade pattern is to simplify and unify functionalities.

In this way, the client does not have to understand the complexity on the other side of the facade.

See the following example of a Facade pattern.

Think of a mobile phone that we must turn on and for this, it is necessary to execute several actions.

Facade

Let’s define the different functionalities of this example.


package patterns.facade;

public class Battery {

    public void on() {
        System.out.println("Battery on");
    }

    public void off() {
        System.out.println("Battery off");
    }
}


package patterns.facade;

public class CPU {

    public void bootLoad() {
        System.out.println("CPU boot loaded");
    }

    public void shutDown() {
        System.out.println("CPU shutdown");
    }
}

From this interface, MobileService will implement Wifi and GPS services.


package patterns.facade;

public interface MobileService {

    void start();
    void close();
}


package patterns.facade;

public class GPSService implements MobileService {
    @Override
    public void start() {
        System.out.println("GPS Service started");
    }

    @Override
    public void close() {
        System.out.println("GPS Service closed");
    }
}


package patterns.facade;

public class WifiSevice implements MobileService {
    @Override
    public void start() {
        System.out.println("WIFI Service started");
    }

    @Override
    public void close() {
        System.out.println("WIFI Service started");
    }
}


Our class represents Mobile.

The mobile has as attributes the battery, the cpu and the services.


package patterns.facade;

import java.util.List;

public class Mobile {

    private final Battery battery;
    private final CPU cpu;
    private final List<MobileService> mobileServices;

    public Mobile(Battery battery, CPU cpu, List<MobileService> mobileServices) {
        this.battery = battery;
        this.cpu = cpu;
        this.mobileServices = mobileServices;
    }

    public CPU getCpu() {
        return cpu;
    }

    public Battery getBattery() {
        return battery;
    }

    public List<MobileService> getMobileServices() {
        return mobileServices;
    }
}

Let’s define the facade that will simplify all mobile phone on and off operations.

Note that the facade will expose two “ON”, “OFF” methods.
All the rest happens inside the facade, and the client does not need to understand the sequence of actions to turn on / off the phone.


package patterns.facade;

import java.util.Arrays;
import java.util.List;

public class MobileFacade {

    public Mobile on() {

        Battery battery = new Battery();
        battery.on();

        CPU cpu = new CPU();
        cpu.bootLoad();

        MobileService gps = new GPSService();
        gps.start();

        MobileService wifi = new WifiSevice();
        wifi.start();

        List<MobileService> mobileServices = Arrays.asList(gps, wifi);

        Mobile mobile = new Mobile(battery, cpu, mobileServices);

        return mobile;
    }

    public void off(Mobile mobile) {

        for(MobileService service :mobile.getMobileServices()) {
            service.close();
        }
        mobile.getCpu().shutDown();
        mobile.getBattery().off();
    }
}

We tested the Facade from our client.


package patterns.facade;

public class ClientFacadePatternExample {

    public static void main(String[] args) {

        MobileFacade facade = new MobileFacade();
        Mobile mobile = facade.on();

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

        facade.off(mobile);
    }
}

Output:

--------------- ON ---------------
Battery on
CPU boot loaded
GPS Service started
WIFI Service started

--------------- OFF ---------------
GPS Service closed
WIFI Service started
CPU shutdown
Battery off

Conclusion

As you saw with the example, this pattern is quite simple to implement and will help you to give your service clients easier access by unifying features.

You can review this code GitHub

Hi! If you find my posts helpful, please support me by inviting me for a coffee :)

See also