Design Patterns Facade
The Facade pattern provides a single, simple interface to a complex system of classes. It hides the internal complexity and gives the client one clean entry point to get the job done.
Think of a hotel concierge. You do not call the kitchen, housekeeping, the transport company, and the spa individually. You call the concierge once. The concierge coordinates all those departments on your behalf. You give one instruction and receive one result.
The Home Theater Example
You want to watch a movie at home. Without a facade, you must:
1. Turn on the projector 2. Set projector input to HDMI 3. Turn on the amplifier 4. Set amplifier to surround mode 5. Turn on the media player 6. Set media player to Movie mode 7. Dim the lights to 20% 8. Close the blinds 9. Press Play
With a Facade:
homeTheater.watchMovie("Inception")
One method. All 9 steps happen automatically behind the scenes.
Visual Diagram: Facade as a Front Door
CLIENT │ │ calls one method ▼ +-------------------------+ | FACADE | ← single entry point | watchMovie() | | endMovie() | +-------------------------+ │ │ │ ▼ ▼ ▼ +-------+ +-------+ +--------+ |Projec-| |Ampli- | |Media | |tor | |fier | |Player | +-------+ +-------+ +--------+ │ ▼ +-------+ |Lights | +-------+ Client sees only the Facade. Subsystems stay hidden behind it.
Key Participants
Facade
The simplified interface. It knows which subsystem classes to call and in what order. It delegates work to the subsystems but never implements subsystem logic itself.
Subsystems
The complex classes that do the real work. They have no reference to the Facade — they operate independently. Advanced clients can still access subsystems directly when they need fine-grained control.
Client
Works with the Facade only. The client stays shielded from every internal detail of the subsystems.
Code Walkthrough in Python
Step 1 — Define the Subsystem Classes
class Projector:
def on(self): print("Projector ON")
def set_hdmi(self): print("Projector: HDMI input selected")
def off(self): print("Projector OFF")
class Amplifier:
def on(self): print("Amplifier ON")
def set_surround(self): print("Amplifier: Surround sound ON")
def off(self): print("Amplifier OFF")
class MediaPlayer:
def on(self): print("Media Player ON")
def play(self, movie): print(f"Playing: {movie}")
def stop(self): print("Media Player: Stopped")
def off(self): print("Media Player OFF")
class Lights:
def dim(self, level): print(f"Lights dimmed to {level}%")
def full(self): print("Lights: Full brightness")
Step 2 — Build the Facade
class HomeTheaterFacade:
def __init__(self, projector, amplifier, player, lights):
self.projector = projector
self.amplifier = amplifier
self.player = player
self.lights = lights
def watch_movie(self, movie):
print("--- Getting ready to watch a movie ---")
self.lights.dim(20)
self.projector.on()
self.projector.set_hdmi()
self.amplifier.on()
self.amplifier.set_surround()
self.player.on()
self.player.play(movie)
def end_movie(self):
print("--- Shutting down home theater ---")
self.player.stop()
self.player.off()
self.amplifier.off()
self.projector.off()
self.lights.full()
Step 3 — Client Uses the Facade
projector = Projector()
amplifier = Amplifier()
player = MediaPlayer()
lights = Lights()
theater = HomeTheaterFacade(projector, amplifier, player, lights)
theater.watch_movie("Inception")
# All 7 setup steps fire automatically
theater.end_movie()
# All shutdown steps fire automatically
Facade vs Direct Access
WITHOUT FACADE WITH FACADE
--------------------------- ---------------------
lights.dim(20) theater.watch_movie("Inception")
projector.on()
projector.set_hdmi()
amplifier.on()
amplifier.set_surround()
player.on()
player.play("Inception")
Client must know every class. Client knows one class.
Client must know the correct order. Facade handles order.
Change in subsystem breaks client. Change in subsystem = update Facade only.
Facade Does Not Lock Out Direct Access
The Facade is optional — it does not block advanced clients from going directly to subsystems. A power user can still call amplifier.set_equalizer("bass_boost") directly if the Facade does not expose that option.
CASUAL USER: theater.watch_movie("Inception")
↓ facade handles everything
POWER USER: theater.watch_movie("Inception")
amplifier.set_equalizer("bass_boost")
↓ facade + direct subsystem access
Real-World Uses of Facade
USE CASE FACADE EXAMPLE
-------------------------------------------------
E-commerce checkout OrderFacade.checkout()
→ inventory check
→ payment processing
→ shipping calculation
→ email confirmation
Compiler Compiler.compile(source)
→ lexer
→ parser
→ semantic analyzer
→ code generator
Operating system API File.open(path)
→ permission check
→ disk lookup
→ buffer allocation
→ file handle return
Database ORM User.save()
→ validation
→ SQL generation
→ connection pooling
→ query execution
Facade and the Principle of Least Knowledge
The Law of Demeter (Principle of Least Knowledge) states that a class should talk only to its immediate friends — not to strangers. Without Facade, the client must know and call many subsystem classes. With Facade, the client only knows one class.
WITHOUT FACADE (violates Least Knowledge): Client → Projector → HDMI module → display controller → ... WITH FACADE (follows Least Knowledge): Client → Facade → (handles everything internally)
Facade vs Similar Patterns
+-------------+----------------------------------------------+ | Pattern | What it does | +-------------+----------------------------------------------+ | Facade | Simplifies access to a complex subsystem | | Adapter | Makes incompatible interfaces work together | | Mediator | Centralizes communication between objects | | Proxy | Controls access to a single object | +-------------+----------------------------------------------+ Facade simplifies MANY classes into one entry point. Adapter converts ONE interface to another. Mediator coordinates BEHAVIOR between objects.
When to Use the Facade Pattern
Use Facade When:
- A subsystem has grown complex and clients only need a fraction of its features.
- You want to layer a subsystem — Facade becomes the public API; everything else becomes internal.
- You want to reduce the number of objects clients interact with.
- You are building a library or SDK and want to hide internal implementation details.
Avoid Facade When:
- Clients genuinely need fine-grained control over every subsystem — a Facade forces them into detours.
- The "simplification" is actually just a new layer of complexity with no real reduction in the client's cognitive load.
Advantages and Disadvantages
Advantages
- Isolates clients from subsystem complexity — easier to use and understand.
- Reduces coupling between client code and subsystem internals.
- Subsystem internals can change without breaking client code.
Disadvantages
- Risk of becoming a "god object" — a Facade that does too much becomes its own problem.
- Advanced capabilities of subsystems may be hidden from clients who need them.
Quick Summary
FACADE PATTERN — AT A GLANCE
Problem: A complex subsystem has too many classes and methods.
Clients must know all of them to get anything done.
Solution: Provide a single simplified class that coordinates
the subsystem and exposes only what clients need.
Key idea: The Facade delegates to subsystems; it does not
replace them or own their logic.
Best for: Libraries, SDKs, e-commerce flows, compiler stages,
OS abstractions, multimedia pipelines.
The Facade pattern turns a maze of complexity into a single front door. Clients knock once, get what they need, and never have to know what happened inside.
