Back to Overview

Facade Pattern

The Facade Pattern provides a simplified interface to a complex subsystem of classes, library, or framework. It doesn't encapsulate the subsystem but provides a unified interface that makes the subsystem easier to use.

By defining a higher-level interface that makes the subsystem easier to use, the Facade Pattern helps to decouple a client from a complex subsystem.

Problem

Imagine you have a complex system with many moving parts, and you need to use only a small portion of its functionality. This might be a third-party library, a large framework, or just a subset of your own complex codebase. How do you provide a simple interface for common use cases without exposing all the underlying complexity?

Client Facade SubsystemA SubsystemB SubsystemC SubsystemD SubsystemE SubsystemF Uses Complex Subsystem

Components

Implementation Example

Let's implement a Home Theater Facade that simplifies the operations of a complex home theater system:

// Subsystem components
class TV {
    turnOn() {
        console.log("TV is turned on");
    }
    
    turnOff() {
        console.log("TV is turned off");
    }
    
    setInput(input) {
        console.log(`TV input set to ${input}`);
    }
}

class AudioSystem {
    turnOn() {
        console.log("Audio system is turned on");
    }
    
    turnOff() {
        console.log("Audio system is turned off");
    }
    
    setVolume(level) {
        console.log(`Audio volume set to ${level}`);
    }
    
    setSurroundSound() {
        console.log("Surround sound enabled");
    }
}

class StreamingPlayer {
    turnOn() {
        console.log("Streaming player is turned on");
    }
    
    turnOff() {
        console.log("Streaming player is turned off");
    }
    
    play(movie) {
        console.log(`Playing "${movie}"`);
    }
    
    stop() {
        console.log("Stopped playback");
    }
}

class Lights {
    dim(level) {
        console.log(`Lights dimmed to ${level}%`);
    }
    
    brighten() {
        console.log("Lights brightened to 100%");
    }
}

// Facade
class HomeTheaterFacade {
    constructor(tv, audio, streamingPlayer, lights) {
        this.tv = tv;
        this.audio = audio;
        this.streamingPlayer = streamingPlayer;
        this.lights = lights;
    }
    
    watchMovie(movie) {
        console.log("Get ready to watch a movie...");
        this.lights.dim(10);
        this.tv.turnOn();
        this.audio.turnOn();
        this.audio.setSurroundSound();
        this.audio.setVolume(5);
        this.streamingPlayer.turnOn();
        this.tv.setInput("HDMI1");
        this.streamingPlayer.play(movie);
    }
    
    endMovie() {
        console.log("Shutting down the home theater...");
        this.streamingPlayer.stop();
        this.streamingPlayer.turnOff();
        this.audio.turnOff();
        this.tv.turnOff();
        this.lights.brighten();
    }
}

// Client code
const tv = new TV();
const audio = new AudioSystem();
const streamingPlayer = new StreamingPlayer();
const lights = new Lights();

const homeTheater = new HomeTheaterFacade(tv, audio, streamingPlayer, lights);

// Simple interface for the client
homeTheater.watchMovie("Inception");
// Later...
homeTheater.endMovie();

Interactive Demo: Home Theater Facade

Experience how the Facade pattern simplifies controlling a complex home theater system.

TV
Status: Off
Audio System
Status: Off
Streaming Player
Status: Off
Lights
Brightness: 100%
TV IS OFF
// System logs will appear here

Without Facade (Complex Direct Usage):

When to Use

Benefits

Real-World Uses