Facade Pattern

⭐ Interview Importance: HIGH
⏱️ Revision Time: 1 min

Concept

Category: Structural Pattern

The Facade Pattern provides a simplified, higher-level interface to a complex subsystem of classes, making the subsystem incredibly easy to use.

The word “Facade” literally means the front exterior of a building. It hides all the messy wiring, plumbing, and structural supports behind a clean, pretty wall.

The Mental Model

Imagine you are rendering a 3D video game.
To render a single frame, the game engine must:

  1. Initialize the GraphicsCardController.
  2. Load shaders via the ShaderManager.
  3. Calculate lighting via the RayTracingEngine.
  4. Flush the MemoryBuffer.

If you write these 4 lines of highly complex, low-level C++ code directly in your GameUI.tsx file every time you want to render a frame, you have violently coupled your beautiful UI to the terrifying hardware subsystems.

The Facade Solution:
You create a single class called GameEngineFacade. You give it one method: .renderFrame().
Inside .renderFrame(), you hide all 4 lines of the messy subsystem logic. The GameUI just calls engine.renderFrame() and has absolutely no idea that shaders or memory buffers even exist!

Implementation

// --- THE MESSY SUBSYSTEMS ---
class CPU {
    freeze() { console.log("CPU Freezing..."); }
    jump(position: string) { console.log(`CPU jumping to ${position}...`); }
    execute() { console.log("CPU Executing..."); }
}

class Memory {
    load(position: string, data: string) { console.log(`Loading ${data} into ${position}...`); }
}

class HardDrive {
    read(lba: string, size: number) { return `[Boot Sector Data]`; }
}

// --- THE FACADE ---
class ComputerFacade {
    private cpu: CPU;
    private memory: Memory;
    private hardDrive: HardDrive;

    constructor() {
        // The Facade handles the ugly instantiation of the subsystems
        this.cpu = new CPU();
        this.memory = new Memory();
        this.hardDrive = new HardDrive();
    }

    // The single, beautiful, easy-to-use method!
    public turnOn() {
        console.log("--- Starting Computer ---");
        this.cpu.freeze();
        
        // The Facade coordinates the complex interactions between subsystems
        const bootData = this.hardDrive.read("0x00", 1024);
        this.memory.load("0x00", bootData);
        
        this.cpu.jump("0x00");
        this.cpu.execute();
        console.log("--- Computer is ON ---");
    }
}

// --- THE CLIENT ---
// The client doesn't need to know anything about memory addresses or CPU states!
const computer = new ComputerFacade();
computer.turnOn();

Facade vs Utility Class

A common question is: “Isn’t a Facade just a Utility Class (like MathUtils)?”
No. A Utility class is a collection of random, independent, static helper functions (formatDate(), capitalize()).
A Facade is a stateful object that specifically coordinates interactions across multiple different classes within a unified subsystem.

Interview Questions

Q: Does the Facade pattern physically prevent developers from accessing the underlying subsystems?
A: No. A Facade is not a security measure. The CPU and Memory classes are still perfectly accessible if a developer truly needs to do something extremely low-level and specific that the Facade doesn’t cover. The Facade just provides a default, easy “Happy Path” for 99% of standard use cases.

Q: Can you have multiple Facades in one application?
A: Yes! In a massive Microservices architecture, an “API Gateway” is literally just a giant network-level Facade. You might have a /users Facade that coordinates the Auth, Billing, and Profile microservices, and a /products Facade that coordinates the Inventory, Pricing, and Review microservices.