Facade
Provide a unified, simplified interface to a set of interfaces in a subsystem, making the subsystem easier to use.
Intent
Define a higher-level interface that shields clients from the complexity of a subsystem by exposing only the operations they actually need, delegating the orchestration of multiple internal components behind a single entry point.
Problem
Your subsystem has grown into many interrelated classes with intricate initialization sequences and complex dependencies. Clients that need to perform common tasks must understand and coordinate numerous objects, leading to tight coupling and fragile code that breaks whenever the subsystem evolves.
Solution
Create a facade class that provides a simple, high-level API for the most common use cases. The facade knows which subsystem classes are responsible for each request and delegates accordingly. Clients interact with the facade instead of the subsystem directly, though the subsystem remains accessible for advanced scenarios.
Participants
- Facade -- provides a simplified API and delegates to subsystem objects
- Subsystem classes -- implement the actual functionality; unaware of the facade
- Client -- calls the facade instead of manipulating subsystem objects directly
Advantages
- Reduces coupling between clients and a complex subsystem
- Provides a convenient default configuration for common use cases
- Promotes subsystem independence -- internal changes stay behind the facade
- Does not prevent direct subsystem access when advanced control is needed
Disadvantages
- The facade can become a 'god object' if too many responsibilities accumulate
- May hide useful lower-level features, tempting developers to bypass the facade
- Adds an additional layer that must be kept in sync with the evolving subsystem
Real-World Analogy
A hotel concierge acts as a facade. When you ask the concierge to arrange a city tour, they coordinate the taxi service, the tour guide company, and the restaurant reservation system. You interact with one person instead of calling three separate services yourself.
Use Cases
- Simplifying a complex email-sending subsystem (SMTP connection, template engine, attachment handler) behind a single sendEmail() call
- Providing a startup/shutdown method for a home-theater system with projector, amplifier, and streaming player
- Wrapping a multi-step report-generation pipeline (data fetching, transformation, PDF rendering) in a single generateReport() method
- Offering a simplified API for a complex third-party SDK
- Encapsulating database migration steps (backup, schema diff, migration, verification) behind a migrate() call
Code Examples
A HomeTheaterFacade wraps multiple subsystem classes (projector, amplifier, streaming player) and exposes simple watchMovie/endMovie methods.