1. The Problem
Problem: Too Much Complexity Leaking to the Client
Large systems expose dozens of classes, configuration steps, and interdependent workflows. Clients end up doing this:
subsystemA = A()
subsystemA.setup()
subsystemB = B()
subsystemC = C()
subsystemB.connect(subsystemC)
subsystemA.execute()
subsystemC.cleanup()
Problems:
- Clients must understand internal details
- High coupling to low-level APIs
- Repeated boilerplate everywhere
- Hard to use, hard to maintain
- Changes in internals break callers
You need a simple unified API over a complicated system.
2. The Facade Pattern: Provide a Simple Interface to a Complex System
Facade hides complexity by providing a single high-level entry point.
Core idea:
- Wrap a complicated subsystem
- Expose a clean, minimal interface
- Internals remain untouched
- Client deals with one object, not many
A Facade system has:
- Subsystems — complex classes doing real work
- Facade — orchestrates subsystems and gives a simple API
You get:
- Simpler external API
- Reduced coupling
- Easier evolution
- Cleaner code on the client side
Use Facade when:
- A system is too complex or noisy to use directly
- You want to shield clients from internal changes
- You want a “default usage path”
- You want a simple integration boundary
3. Implementation: Facade in Python
Subsystems (complex system)
class AudioSystem:
def turn_on(self):
return "Audio System ON"
def set_volume(self, level):
return f"Volume set to {level}"
class VideoSystem:
def turn_on(self):
return "Video System ON"
def set_resolution(self):
return "Resolution set to 4K"
class StreamingApp:
def open(self):
return "Streaming App Opened"
def play(self, movie):
return f"Playing {movie}"
Facade simplifying everything
class HomeTheaterFacade:
def __init__(self):
self.audio = AudioSystem()
self.video = VideoSystem()
self.app = StreamingApp()
def watch_movie(self, movie):
steps = [
self.audio.turn_on(),
self.audio.set_volume(50),
self.video.turn_on(),
self.video.set_resolution(),
self.app.open(),
self.app.play(movie)
]
return "\n".join(steps)
Client now interacts with ONE object
theater = HomeTheaterFacade()
print(theater.watch_movie("Inception"))
Output:
Audio System ON
Volume set to 50
Video System ON
Resolution set to 4K
Streaming App Opened
Playing Inception
Client does not know or care how many subsystems exist.
4. When to Use (and Not Use) Facade
You likely need Facade when you see:
- Callers manually coordinating multiple subsystems
- Too many setup/config steps everywhere
- Tight coupling between client and internal classes
- Repeated integration code across the codebase
Benefits:
- Reduced cognitive load
- Stable API over evolving internals
- Cleaner client code
- Encourages separation of concerns
Pitfalls:
- Facade becoming “God Object” if overloaded
- Hiding too much can reduce flexibility
- If subsystems are already simple → unnecessary abstraction
- Over-facading leads to layered indirection