Facade Design Pattern


Here, we will see how to create Facade Design Pattern with example.

Facade Design Pattern

The Facade Design Pattern is a structural pattern that provides a simplified interface to a complex system. It hides the complexities of the system by exposing a unified, easy-to-use interface, allowing clients to interact with the subsystem without needing to understand the details.

Example - Home Theater System

A modern home theater system may include several components, such as a TV, speakers, DVD player, gaming console, and more. Instead of manually turning on each device, adjusting volume, and setting inputs, a home theater remote control acts as a facade. We will explain in detail lator part of the article with code example.

Facade Design Pattern

Advantages of the Facade Pattern

  • Simplifies usage - It reduces the complexity of the system by providing a simple interface, making it easier for the client to interact with the system.
  • Loose coupling - The client interacts with the facade rather than the complex system directly, which helps decouple the client from the system’s internal logic.
  • Improves readability and maintainability - It makes the system easier to understand and maintain, especially when a system contains multiple interconnected classes or modules.
  • Centralized access - The facade serves as a single point of access to different parts of the system, improving organization.
  • Enhanced flexibility - Facade can evolve and be modified without impacting clients, as long as the facade's interface remains unchanged.

When to Use the Facade Pattern

  • Complex systems - When a system contains many complex and tightly coupled classes, and you want to simplify how clients interact with it.
  • Legacy systems - When working with a legacy codebase that is complex, the facade pattern can help create a modern, easy-to-use interface while keeping the core functionality unchanged.
  • Multiple subsystems - When a system consists of multiple subsystems, and you want to present a simplified interface to clients while allowing subsystems to evolve independently.
  • Ease of integration - When you need to integrate with external systems but want to shield your system from the complexity of those external interfaces.

Problems Without the Facade Pattern

  • Tight coupling - Without a facade, clients need to know how to interact with each class and subsystem directly, leading to tightly coupled code.
  • Complex client code - The client must handle multiple complex interactions with the system, which increases the complexity of the client code and can lead to errors.
  • Difficult to maintain - As the system grows more complex, maintaining the code becomes harder without a central point that abstracts system behavior.
  • Reduced flexibility - If the client is tightly coupled to multiple classes of a subsystem, modifying or extending the system becomes difficult without breaking the client’s code.

Real-World Example of the Facade Pattern

Home Theater System: A modern home theater system may include several components, such as a TV, speakers, DVD player, gaming console, and more. Instead of manually turning on each device, adjusting volume, and setting inputs, a home theater remote control acts as a facade. It provides a simplified interface (buttons for "Watch Movie" or "Play Game"), which internally activates the appropriate components and configures them correctly without requiring the user to understand the technical details.

Here's a deeper look at how the home theater example works in this context:

Home Theater Components:

A typical home theater might include:

  1. TV – Displays video.
  2. Speakers/Amplifier – Provides audio output.
  3. DVD/Blu-ray player – Plays media like movies.
  4. Gaming console – Plays video games.
  5. Streaming device – Allows access to streaming services.

Normally, each of these components would require its own remote control or specific configuration:

  • TV: You'd need to power it on and switch it to the correct input (e.g., HDMI1 for the DVD player).
  • Speakers/Amplifier: You’d need to power on the audio system and adjust the volume.
  • DVD Player: You’d need to insert the disc and press "Play."
  • Gaming console: You’d power it on and switch inputs on the TV again.

The Facade (Remote Control)

Instead of dealing with all these components individually, the remote control acts as a facade by grouping all the commands into simple actions:

  • Watch Movie Button
    • Turns on the TV.
    • Switches the input to the DVD player.
    • Powers on the speakers.
    • Adjusts the volume.
    • Starts playing the DVD.
  • Play Game Button
    • Powers on the TV and gaming console.
    • Switches the TV input to the console.
    • Turns on the speakers.

This means that the user doesn’t need to worry about which input or device to switch on. The remote hides the complexity of managing multiple systems, and the user just interacts with an easy-to-use interface.

How the Remote Works as a Facade

  • Internally, when you press "Watch Movie," the remote sends signals to each device (TV, speakers, DVD player), activating them and adjusting their settings.
  • The user doesn't need to know how to operate each component individually, or even which input to select — they just press one button.

The facade provides a unified and straightforward way to control a complex set of systems, which is the essence of the Facade Design Pattern.

using System;

// Subsystems
public class TV
{
    public void TurnOn()
    {
        Console.WriteLine("TV is now ON");
    }
    public void TurnOff()
    {
        Console.WriteLine("TV is now OFF");
    }
    public void SetInput(string input)
    {
        Console.WriteLine($"TV input set to {input}");
    }
}


public class SoundSystem
{
    public void TurnOn() 
    { 
        Console.WriteLine("Sound System is now ON"); 
    }
    public void TurnOff() 
    { 
        Console.WriteLine("Sound System is now OFF"); 
    }
    public void SetVolume(int level) 
    { 
        Console.WriteLine($"Volume set to {level}"); 
    }
}

public class DVDPlayer
{
    public void TurnOn() 
    { 
        Console.WriteLine("DVD Player is now ON"); 
    }
    public void Play() 
    { 
        Console.WriteLine("Playing movie on DVD Player"); 
    }
    public void TurnOff() 
    { 
        Console.WriteLine("DVD Player is now OFF"); 
    }
}

public class GamingConsole
{
    public void TurnOn() 
    { 
        Console.WriteLine("Gaming Console is now ON"); 
    }
    public void Play() 
    { 
        Console.WriteLine("Playing game on Gaming Console"); 
    }
    public void TurnOff() 
    { 
        Console.WriteLine("Gaming Console is now OFF"); 
    }
}

// Facade
public class HomeTheaterFacade
{
    private TV tv;
    private SoundSystem soundSystem;
    private DVDPlayer dvdPlayer;
    private GamingConsole gamingConsole;

    public HomeTheaterFacade(TV tv, SoundSystem soundSystem, DVDPlayer dvdPlayer, GamingConsole gamingConsole)
    {
        this.tv = tv;
        this.soundSystem = soundSystem;
        this.dvdPlayer = dvdPlayer;
        this.gamingConsole = gamingConsole;
    }

    public void WatchMovie()
    {
        Console.WriteLine("\nStarting Movie Mode...");
        tv.TurnOn();
        tv.SetInput("DVD Player");
        soundSystem.TurnOn();
        soundSystem.SetVolume(30);
        dvdPlayer.TurnOn();
        dvdPlayer.Play();
    }

    public void PlayGame()
    {
        Console.WriteLine("\nStarting Game Mode...");
        tv.TurnOn();
        tv.SetInput("Gaming Console");
        soundSystem.TurnOn();
        soundSystem.SetVolume(40);
        gamingConsole.TurnOn();
        gamingConsole.Play();
    }

    public void EndMovie()
    {
        Console.WriteLine("\nEnding Movie Mode...");
        dvdPlayer.TurnOff();
        soundSystem.TurnOff();
        tv.TurnOff();
    }

    public void EndGame()
    {
        Console.WriteLine("\nEnding Game Mode...");
        gamingConsole.TurnOff();
        soundSystem.TurnOff();
        tv.TurnOff();
    }
}

// Client
class Program
{
    static void Main(string[] args)
    {
        // Subsystems
        TV tv = new TV();
        SoundSystem soundSystem = new SoundSystem();
        DVDPlayer dvdPlayer = new DVDPlayer();
        GamingConsole gamingConsole = new GamingConsole();

        // Facade
        HomeTheaterFacade homeTheater = new HomeTheaterFacade(tv, soundSystem, dvdPlayer, gamingConsole);

        // Client interaction through the Facade
        homeTheater.WatchMovie();
        homeTheater.EndMovie();
        homeTheater.PlayGame();
        homeTheater.EndGame();
    }
}

Explanation

  • Subsystems - Classes TV, SoundSystem, DVDPlayer, and GamingConsole represent individual components of the home theater system.
  • Facade - The HomeTheaterFacade class encapsulates the complex interactions between these components by exposing simple methods like WatchMovie and PlayGame.
  • Client - The Program class interacts with the home theater using the facade, which hides the complexity of individual subsystem interactions.

Output

Facade Design Pattern

Application of the Facade Design Pattern

  • Library Integration: When integrating third-party libraries or services into an application, the facade pattern can be used to provide a simplified interface to these services.
  • Complex APIs: In software that interacts with complex APIs, such as cloud services or operating system-level features, a facade can help abstract the underlying complexity.
  • Enterprise Applications: In large-scale enterprise applications with many interconnected modules, facades can be used to simplify module interaction and improve maintainability.
  • Subsystem Management: In applications where different subsystems are used (e.g., file system, database, logging), a facade can unify access to these subsystems, making the application more modular.

Prev Next

Top Articles

  1. What is JSON
  2. How to convert a javaScript object in JSON object
  3. Some Important JSON Examples
  4. Common JSON Interview Question