1. Definition
The Facade Design Pattern provides a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
2. Problem Statement
Consider a scenario where you are building a home automation system. This system can control lights, the stereo, and the home theater system. Each of these components has its own complex interface. Turning on a movie involves multiple steps like dimming the lights, setting the stereo to surround sound, and finally, playing the movie. How can you provide a simple interface for users to perform these tasks without getting overwhelmed by the complexity of individual components?
3. Solution
Introduce a Facade that provides simplified methods for complex actions. The Facade will handle the intricacies of managing the subsystems, offering the client a cleaner and more straightforward interface.
4. Real-World Use Cases
1. Home automation systems providing simplified controls for complex actions.
2. A computer’s startup process.
3. Customer support systems that provide a single touchpoint for a variety of issues.
5. Implementation Steps
1. Identify a simpler, unified interface that can cover the complex functionalities of a subsystem.
2. Create a Facade class that aggregates the subsystems and provides the simplified methods.
3. Clients will then interact with the Facade instead of the subsystem directly.
6. Implementation
// Subsystem 1
public class Lights {
public void dim() {
System.out.println("Lights are dimmed.");
}
}
// Subsystem 2
public class Stereo {
public void setSurroundSound() {
System.out.println("Stereo is set to surround sound.");
}
}
// Subsystem 3
public class HomeTheater {
public void playMovie() {
System.out.println("Movie is playing now.");
}
}
// Facade
public class HomeAutomationFacade {
private Lights lights;
private Stereo stereo;
private HomeTheater homeTheater;
public HomeAutomationFacade(Lights lights, Stereo stereo, HomeTheater homeTheater) {
this.lights = lights;
this.stereo = stereo;
this.homeTheater = homeTheater;
}
public void watchMovie() {
lights.dim();
stereo.setSurroundSound();
homeTheater.playMovie();
}
}
// Client Code
public class Client {
public static void main(String[] args) {
Lights lights = new Lights();
Stereo stereo = new Stereo();
HomeTheater homeTheater = new HomeTheater();
HomeAutomationFacade facade = new HomeAutomationFacade(lights, stereo, homeTheater);
facade.watchMovie();
}
}
Output:
Lights are dimmed. Stereo is set to surround sound. Movie is playing now.
Explanation:
In this example, the HomeAutomationFacade provides a simple method watchMovie() to activate multiple systems. It abstracts the complexity from the client, offering a unified interface to achieve the desired result. The client doesn't need to worry about the intricacies of each subsystem.
7. When to use?
1. When you want to provide a simple interface to a complex subsystem.
2. To decouple clients from the complexities of the subsystem components, promoting subsystem independence and portability.
3. When you want to layer your subsystems.