Facade
What This Concept Is
Facade is a structural pattern that provides a small, simple interface over a larger, more complex subsystem. The subsystem still exists; the Facade does not hide it or prevent advanced use. It just offers the 80% path as a single coherent API.
Key traits:
- the Facade is additive. Clients who need the subsystem directly can still reach it.
- the Facade does not add new behavior that is not already in the subsystem; it orchestrates existing behavior.
- the Facade typically lives in the same layer as the subsystem, not in the domain.
The problem it absorbs: most callers need only the common workflow of a complex subsystem, and letting them wire it themselves produces repetition, bugs, and knowledge-you-should-not-need.
Why It Matters Here
Facade is where the Law of Demeter and "Don't Repeat Yourself" collide with "keep simple clients simple." It is how standard libraries survive having 400 classes: each module provides one or two Facades that cover the common case, and the rest is available to power users.
A Facade is also the most honest abstraction over a subsystem you control. You are not pretending the subsystem is simple; you are admitting that most callers do not need the complexity.
Concrete Example
// Subsystem: many pieces
class Amplifier { void on(); void setVolume(int); void off(); }
class DvdPlayer { void on(); void play(String m); void stop(); void off(); }
class Projector { void on(); void wideScreenMode(); void off(); }
class TheaterLights { void dim(int p); void on(); }
class PopcornPopper { void on(); void pop(); void off(); }
// Facade: one simple, orchestrated interface
class HomeTheaterFacade {
private final Amplifier amp;
private final DvdPlayer dvd;
private final Projector proj;
private final TheaterLights lights;
private final PopcornPopper popper;
// ...constructor wires all five...
public void watchMovie(String movie) {
popper.on(); popper.pop();
lights.dim(10);
proj.on(); proj.wideScreenMode();
amp.on(); amp.setVolume(5);
dvd.on(); dvd.play(movie);
}
public void endMovie() {
popper.off(); lights.on(); proj.off();
amp.off(); dvd.stop(); dvd.off();
}
}
Structural sketch:
Client --> Facade --+--> Subsystem piece
+--> Subsystem piece
+--> Subsystem piece
+--> ...
Power user ---------> Subsystem piece (still reachable)
Common Confusion / Misconception
- Facade vs Adapter. A Facade simplifies many interfaces into one for convenience. An Adapter reshapes one interface into another for compatibility. Facade changes cardinality; Adapter changes shape.
- A Facade that also translates data types is doing too much. That is an Adapter or a service.
- A Facade is not a God Object. If the Facade grows methods that do not orchestrate the subsystem, it is sliding toward one.
- A Facade that forbids access to the underlying subsystem has become something else (an encapsulating service or a port). Both are legitimate, but they are not Facade.
How To Use It
- Identify the common case workflow across a subsystem. Not every workflow: the common ones.
- Give the Facade a name in the vocabulary of the caller, not the subsystem.
- Delegate, do not reimplement. The subsystem remains the source of truth.
- Leave the subsystem reachable. A Facade earns trust by not pretending to own its parts.
- Re-evaluate when the Facade starts accumulating methods faster than the subsystem does -- that is the smell of a misplaced service.
Check Yourself
- What single question separates Facade from Adapter?
- When is a Facade the wrong answer, and a replacement service the right one?
- Why is a Facade usually the first useful abstraction over a new third-party dependency you own?
Mini Drill or Application
Take a small subsystem you use regularly (a logger, an ORM, a file uploader). Do three things:
- List the 20% of its API that you use in 80% of call sites.
- Write a Facade that covers that 20%.
- Leave at least two methods unimplemented on purpose, with a comment pointing power users back to the underlying subsystem.