Facade

The main goal of the Facade design pattern is to simplify communication between a client and a complex system. In large applications business logic is spread across many components. The Facade gives one interface which hides the complexity of the internal system.

Thanks to the Facade, the client does not need to know details of each class. It only uses the interface provided by the Facade.

Let’s consider a Report Generator application for managing documents. The application has several classes and methods. Called in the right order, they return a report.

The enum Role stores user roles used in the application:

public enum Role {
    ADMIN,
    USER;
}

The User class represents a user who wants to generate a document. The user must be authorized:

public class User {
    private String username;
    private Role role;

    public User(String username, Role role) {
        this.username = username;
        this.role = role;
    }

    public Role getRole() {
        return role;
    }
}

The Report class represents the report to generate:

public class Report {
    private String content;

    Report(String content) { this.content = content; }

    public void exportToPDF() {
        System.out.println("Exporting report to PDF");
        System.out.println(content);
    }
}

The AuthService class handles user authorization:

public class AuthService {
    public boolean hasAccess(User user) {
        return "ADMIN".equals(user.getRole());
    }
}

The DataService class generates data for the report:

public class DataService {
    public String fetchDataForReport() {
        return "Q2 financial data: [revenue, costs, profit...]";
    }
}

The ReportService class generates reports and returns a Report object:

public class ReportService {
    public Report generateReport(String data) {
        return new Report("Report generated based on:\n" + data);
    }
}

Another application (Client) connects to Report Generator. The Client is an external application that connects to the Report Generator and generates a report:

public class Client {
    public static void main (String[] args) {
        User admin = new User("John", Role.ADMIN);

        AuthService authService = new AuthService();
        DataService dataService = new DataService();
        ReportService reportService = new ReportService();

        if (authService.hasAccess(admin)) {
            String data = dataService.fetchDataForReport();
            Report report = reportService.generateReport(data);
            report.exportToPDF();
        } else {
            System.out.println("No permission to generate the report.");
        }
    }
}

The Client class must know how the Report Generator works. It must know all its classes and methods. It must know the order of method calls to generate a report. It also has direct access to Report Generator classes. The Facade gives the Client one interface and hides the details.

Implementation of the Facade pattern

The report-generation logic is moved from Client class to ReportFacade class. The ReportFacade class exposes 1 interface, generateReport(). The Client uses this interface:

public class ReportFacade {

    private AuthService authService = new AuthService();
    private DataService dataService = new DataService();
    private ReportService reportService = new ReportService();

    public void generateReport (User user) {
        if (authService.hasAccess(user)) {
            String data = dataService.fetchDataForReport();
            Report report = reportService.generateReport(data);
            report.exportToPDF();
        } else {
            System.out.println("No permission to generate the report.");
        }
    }
}

Access to other classes and methods is blocked. In Java, classes can be moved to a separate package and the public access modifier can be removed. Then only ReportFacade will have access. The Client will not.

The Client class now calls only generateReport() from the Facade. In this case, the User class cannot be hidden. The Client must use it.

public class Client {
    public static void main (String[] args) {
        User admin = new User("Jan", Role.ADMIN);

        ReportFacade reportFacade = new ReportFacade();
        reportFacade.generateReport(admin);
    }
}

The Client no longer needs to know the order of method calls. All report logic is hidden. The Client needs to know only one interface.

Summary

The Facade pattern is a clean way to organize complex systems. It offers simple and consistent access points. The Facade isolates the client from the system. It separates the business logic layer from internal methods. This makes code safer and easier to change.

The Facade is common in the service layer of web apps and in integrations with external services. The Facade acts like a gate. It ties many classes and components into one logical entry point.


The Facade pattern is similar to the Adapter pattern, but they have different goals:

  • the goal of Facade is to provide a simple interface to a system or subsystem,
  • the goal of Adapter is to modify an interface so it fits the client’s needs.