Skip to main content

Introduction To Facade Pattern

The Facade design pattern is a structural design pattern that provides a simplified interface to a complex system. It involves creating a wrapper interface over a complex system to hide its complexities. This pattern involves a single class that provides simplified methods required by the client and delegates calls to methods of existing system classes.

Think of it as the facade of a building. The facade is an interface to the outside world that hides the complex internal system. In the same way, a Facade in programming provides a simple interface to a complex system while still allowing access to its internal structure if necessary.

Here's a simple example of the Facade design pattern in TypeScript. Consider that we have a complex system for preparing various types of coffee:

class Grinder {
grindBeans() {
console.log("Grinding beans...");
}
}

class Boiler {
boilWater() {
console.log("Boiling water...");
}
}

class Brewer {
brewCoffee() {
console.log("Brewing coffee...");
}
}

Each of these classes does something specific and in combination they can make coffee, but it's complicated to deal with them directly, so we create a Facade:

class CoffeeMakerFacade {
private grinder: Grinder;
private boiler: Boiler;
private brewer: Brewer;

constructor(grinder: Grinder, boiler: Boiler, brewer: Brewer) {
this.grinder = grinder;
this.boiler = boiler;
this.brewer = brewer;
}

makeCoffee() {
this.grinder.grindBeans();
this.boiler.boilWater();
this.brewer.brewCoffee();
console.log("Coffee is ready!");
}
}

Now the client code can use the CoffeeMakerFacade to make coffee in a simplified manner:

let grinder = new Grinder();
let boiler = new Boiler();
let brewer = new Brewer();

let coffeeMaker = new CoffeeMakerFacade(grinder, boiler, brewer);

coffeeMaker.makeCoffee(); // This will output: "Grinding beans... Boiling water... Brewing coffee... Coffee is ready!"

In this example, the CoffeeMakerFacade simplifies the interface of making coffee and hides the complexity of the subsystem from the client. The client doesn't need to know about the Grinder, Boiler, or Brewer classes or their methods. They just need to call the makeCoffee method on the CoffeeMakerFacade.

That's the basic idea of the Facade design pattern. It's particularly useful when you want to provide a simple interface to a complex subsystem, when there are a lot of interdependencies between classes, or when you want to layer your subsystems.

When Do You Need The Facade Pattern

The Facade design pattern is typically chosen when certain design smells or patterns emerge that indicate an overly complex or confusing system of classes. Here are a few situations where the Facade pattern might be beneficial:

  1. Rampant Dependencies: If you notice that a lot of classes in your system are dependent on a wide array of other classes or subsystems, it can lead to high coupling and complex interactions. The Facade pattern can simplify these dependencies by providing a single interface to multiple subsystems, reducing the overall complexity and coupling.

  2. Overwhelming Complexity: When you're dealing with a complex subsystem with multiple interdependent classes or operations, using them directly can be overwhelming and error-prone. The Facade pattern can wrap these complexities and provide a simple, user-friendly interface to interact with.

  3. Overexposure of Inner Workings: If client code is overexposed to the internals of a subsystem, it can lead to code that's hard to understand and maintain. A facade can encapsulate the subsystem's functionality and provide only the necessary features to clients.

  4. Need for a Layered Architecture: If you need to build a multi-layered or tiered architecture (like Presentation-Business-Data tiered architecture), Facade can be used to define entry points to each layer or tier. This way, the complexity of interactions between layers can be effectively managed.

  5. Need for a Simplified API: When building libraries or APIs, providing a simple interface to clients is crucial for usability. The Facade pattern can be used to simplify the use of a complex library or API, hiding unnecessary complexity and exposing only the necessary functionalities.

  6. Refactoring Legacy Code: Legacy code can often be difficult to work with, especially when it's not feasible to refactor all at once. A Facade can be created to simplify interactions with this code, which can be a step towards its eventual refactoring.

The presence of one or more of these design smells doesn't automatically mean you should use a Facade. However, these can serve as indications that a Facade might be beneficial. Ultimately, the decision to use a Facade or any other design pattern depends on the specific needs and constraints of your project.

What Can You Do Next 🙏😊

If you liked the article, consider subscribing to Cloudaffle, my YouTube Channel, where I keep posting in-depth tutorials and all edutainment stuff for ssoftware developers.

YouTube @cloudaffle