The Facade pattern is a structural design pattern that provides a simplified interface to a complex subsystem. It’s like a friendly receptionist for a large, busy office – you don’t need to know all the inner workings to get what you need.

This pattern allows us to encapsulate the complexities of multiple subsystems behind a single, streamlined facade. By doing so, it not only simplifies usage for clients but also allows for easier maintenance and upgrades of the underlying subsystems without affecting the client code.

Structure

The Facade pattern consists of the following key components:

  • Facade: acts as an interface to the complex system for the client and delegates the client requests to respective subsystem objects
  • Subsystem: implements the complex functionality, and consists of multiple components. Subsystems are not aware of the Facade and work independently with eachother.
  • Client: uses Facade to interact with the system

When to use the Facade Pattern?

  • When you want to provide a simple interface to your complex system
  • When you want to add layers to your system, each layer handling respective functionality

Implementation Example

The code below demonstrates the implementation of the Facade design pattern in Java.

The Receptionist Facade provides a single method, welcomeNewEmployee(), which handles the entire onboarding process. It adapts to different work environments (remote or in-person) by setting up appropriate equipment, completing HR formalities, and providing security access.

// client
public class Solution {

    public static void main(String[] args) {

        ReceptionistFacade receptionist = new ReceptionistFacade();
        receptionist.welcomeNewEmployee("John Doe", "Remote");

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

        receptionist.welcomeNewEmployee("Jane Doe", "In Person");
    }
}

// Facade
class ReceptionistFacade {

    private HumanResources humanResources;
    private ITDepartment itDepartment;
    private SecurityOffice security;

    public ReceptionistFacade() {

        this.humanResources = new HumanResources();
        this.itDepartment = new ITDepartment();
        this.security = new SecurityOffice();
    }

    public void welcomeNewEmployee(String name, String workEnvironment) {
        
        humanResources.onboardNewEmployee(name);
        if (workEnvironment.equals("Remote")) {
            itDepartment.setupLaptop(name);
        } else {
            itDepartment.setupDesktop(name);
        }
        security.issueKeycard(name);

        System.out.println("Receptionist: " + name + " is onboarded!");
    }
}

// Subsystem classes
class HumanResources {

    public void onboardNewEmployee(String name) {

        System.out.println("HR: Onboarding new employee " + name);
    }
}

class ITDepartment {

    public void setupDesktop(String name) {

        System.out.println("IT: Setting up desktop for " + name);
    }

    public void setupLaptop(String name) {

        System.out.println("IT: Setting up laptop for " + name);
    }
}

class SecurityOffice {

    public void issueKeycard(String name) {

        System.out.println("Security: Issuing keycard to " + name);
    }
}

The output of the following program will be:

HR: Onboarding new employee John Doe
IT: Setting up laptop for John Doe
Security: Issuing keycard to John Doe
Receptionist: John Doe is onboarded!

--------------------------------------

HR: Onboarding new employee Jane Doe
IT: Setting up desktop for Jane Doe
Security: Issuing keycard to Jane Doe
Receptionist: Jane Doe is onboarded!