Home Design Patterns Facade

Facade

Structural Gang of Four

“Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.”

Gamma, Helm, Johnson & Vlissides, p. 185

Purpose

A Facade puts one simple door in front of a complicated subsystem. The subsystem keeps all of its power; the Facade just offers the small number of operations that most callers actually want, in the vocabulary those callers already use.

The important thing about a Facade is what it does not do. It does not hide the subsystem. A caller with an unusual need can still reach past it and talk to the parts directly. It is a convenience, not a wall. A Facade that forbids direct access has become something else, and usually something worse.

Design

The Facade holds references to the subsystem classes it coordinates and implements each of its own operations as a short sequence of calls into them. It owns the ordering knowledge: initialize before configure, configure before run, and always release on the way out. That is exactly the knowledge which otherwise gets duplicated, half-remembered, and eventually gotten wrong by every caller in the codebase.

UML class diagram: Client talks to Facade, which delegates to three subsystem classes.
One inbound arrow, several outbound. The client's dependency count drops from three to one, and the sequencing lives in one place.

A Facade should hold no state of its own beyond the references it needs. Once it starts accumulating fields it is no longer simplifying access to a subsystem; it has become a component in its own right, with a lifecycle to manage.

Example

Bringing an Autobot Robotics arm to a ready state is a genuinely fiddly sequence: power up the servo bus, wait for the drives to report ready, home each axis in a specific order so the arm cannot collide with its own fixture, load the tool calibration, zero the force sensors, and only then release the motion interlock. Six subsystems, and an ordering constraint between nearly every pair.

Every application that used the arm had reimplemented that sequence, and no two versions agreed. One skipped the force-sensor zero because it "seemed to work anyway". One homed the axes in the wrong order and had been quietly bending a fixture for months.

The team wrapped it in an ArmSession facade exposing four operations: bringUp(), shutDown(), estop(), and status(). The six subsystems did not change at all. The diagnostics tool, which genuinely needs to home a single axis in isolation, still talks to the homing controller directly, and that is the pattern working as intended rather than a violation of it.

Comparisons

  • Adapter converts an interface you were given into the one you needed. A Facade invents a new, simpler interface that nobody specified. Adapter is about compatibility, Facade about complexity.
  • Mediator also centralizes interaction, but its colleagues know about the mediator and talk through it in both directions. A subsystem behind a Facade has no idea the Facade exists.
  • Singleton is frequently how a Facade gets reached, and that combination is where a lot of Facades go wrong. See the criticisms below.
  • Abstract Factory can hide which concrete subsystem classes a Facade is wired to, if more than one implementation exists.
  • Module is the same instinct applied at a larger scale, to a whole unit of code rather than to a set of collaborating objects.

Why It Exists

My take

Facade exists because of a mismatch between how subsystems are built and how they are used. A well-factored subsystem is decomposed for the benefit of the people maintaining it, with small classes, single responsibilities, and every seam in a sensible place. But that decomposition is what makes it tedious to call. Good internal structure and a good calling experience are different design goals, and a Facade is the acknowledgement that you can have both if you are willing to write one more class.

The deeper reason it matters is that undocumented ordering constraints are one of the most expensive kinds of knowledge a system can hold. When six calls must happen in a particular order and the requirement lives only in the head of whoever wrote it, every new caller is a coin flip. The bent fixture in the example above is not a hypothetical class of bug; that is what this pattern is actually preventing. A Facade converts tribal knowledge into a function signature.

I would also note it is the pattern with the best cost-to-benefit ratio in the catalog. It requires no inheritance, no interface gymnastics, and no runtime indirection. It is one class that calls some other classes in the right order. That it appears in a book alongside Visitor and Flyweight says more about how easy it is to overlook than about how sophisticated it is.

Criticisms

Facades attract scope. The first version has four methods. Then someone needs a variation, and it has nine, and then it has forty and it is a god object with a polite name. The subsystem it was supposed to simplify is now unreachable in practice because everything goes through the Facade, and the Facade is the least maintainable file in the codebase. The failure mode is gradual and every individual step looks reasonable.

It also makes an implicit bet that most callers want the same thing. When that bet is wrong, you get a Facade that nobody can use without working around it, and the workarounds are worse than no Facade at all.

Finally, be careful combining it with Singleton. A global Facade is a very convenient thing to reach for from anywhere, which is another way of saying it is a very convenient way to give every class in the system a dependency on your entire subsystem.