Facade
To start movie night you must switch on the projector, set the amplifier, dim the lights and press play, in the right order.
Write one class with a few high-level methods (watch_movie).
A subsystem has many classes and a fixed common use
The picture from life
At a hotel you say to the front desk: "I want a cab to the airport at six". The desk calls the transport team, checks your bill, informs housekeeping and prints your invoice. You never talk to those departments yourself. The desk is the facade.
The problem
What goes wrong when you do not use it.
To start movie night you must switch on the projector, set the amplifier, dim the lights and press play, in the right order. Every caller repeats these ten calls, and one wrong order breaks the show.
- calls / uses
- A subsystem has many classes and a fixed common use
- You want to cut dependencies between layers
- Newcomers need an easy way in
The idea
How the pattern fixes it.
Write one class with a few high-level methods (watch_movie). Inside, it calls the subsystem in the right order. Callers use the facade; experts can still reach the parts when needed.
- calls / uses
Who is who
- HomeTheater (facade)
- watch(movie) and end().
- Projector, Amp, Lights, Player
- The subsystem classes, unaware of the facade.
- Client
- Calls only the facade.
Build it in steps
- 1List the steps callers always repeat.
- 2Put them in one method with a clear name.
- 3Keep the subsystem classes unchanged.
- 4Point callers to the facade.
Watch it run
Step through the calls. Tap an arrow to jump to it.
One call from the client. That is all it knows.
watch('Dune')The code
Python and Java. Try writing the classes yourself from the diagram first.
class Projector:
def on(self):
return "projector on"
class Amp:
def set_volume(self, level):
return f"amp volume {level}"
class Lights:
def dim(self, percent):
return f"lights {percent}%"
class HomeTheater: # the facade
def __init__(self):
self.projector, self.amp, self.lights = Projector(), Amp(), Lights()
def watch(self, movie):
return [self.projector.on(), self.amp.set_volume(8), self.lights.dim(20), "playing " + movie]
def demo():
return HomeTheater().watch("Dune")What you gain
- Callers learn one method, not ten classes
- The subsystem can change behind it
What it costs
- It can grow into a "god object" that knows too much
- Does not stop anyone from bypassing it
You have already met it in
- requests.get() hides sockets, headers and retries
- A service layer that wraps several repositories
- jQuery as a simple front over messy browser APIs
Often mixed up with
Make it stick
Write an OrderFacade with place_order(item) that calls Inventory, Payment and Shipping in order. Call it from main with one line.