Provide a simplified, unified interface to a complex subsystem — hide the complexity behind a single entry point.
Facade provides a simple interface to a complex body of code — a library, a framework, or any complex set of classes. Clients interact with the Facade instead of the subsystem directly, reducing coupling and cognitive load.
The Facade doesn't prevent access to the subsystem — advanced users can still go direct. It simply provides a convenient, higher-level alternative for common use cases.
A home theatre system has: Amplifier, DVDPlayer, Projector, Lights, Screen, PopcornPopper. Watching a movie means: turning on the popper, lowering lights, pulling down the screen, turning on the projector, setting input, turning on the amp, setting volume, starting the DVD. 8 classes, many method calls, specific order.
A HomeTheatreFacade with a single watchMovie() method hides all of this complexity. The client calls one method.
// Subsystem classes — complex, many methods public class Amplifier { public void on() { System.out.println("Amp on"); } public void setVolume(int v) { System.out.println("Volume: " + v); } public void off() { System.out.println("Amp off"); } } public class DVDPlayer { public void on() { System.out.println("DVD on"); } public void play(String m) { System.out.println("Playing: " + m); } public void stop() { System.out.println("DVD stopped"); } public void off() { System.out.println("DVD off"); } } public class Projector { public void on() { System.out.println("Projector on"); } public void wideScreenMode() { System.out.println("Widescreen mode"); } public void off() { System.out.println("Projector off"); } } public class TheaterLights { public void dim(int pct) { System.out.println("Lights at " + pct + "%"); } } public class Screen { public void down() { System.out.println("Screen down"); } public void up() { System.out.println("Screen up"); } } // Facade — orchestrates the subsystem public class HomeTheatreFacade { private final Amplifier amp; private final DVDPlayer dvd; private final Projector projector; private final TheaterLights lights; private final Screen screen; public HomeTheatreFacade(Amplifier a, DVDPlayer d, Projector p, TheaterLights l, Screen s) { amp=a; dvd=d; projector=p; lights=l; screen=s; } // Simple interface hiding 8 subsystem calls public void watchMovie(String movie) { System.out.println("--- Get ready to watch a movie! ---"); lights.dim(10); screen.down(); projector.on(); projector.wideScreenMode(); amp.on(); amp.setVolume(5); dvd.on(); dvd.play(movie); } public void endMovie() { System.out.println("--- Shutting down theatre ---"); dvd.stop(); dvd.off(); amp.off(); projector.off(); screen.up(); lights.dim(100); } } // Client — one call instead of eight public class Main { public static void main(String[] args) { HomeTheatreFacade theatre = new HomeTheatreFacade( new Amplifier(), new DVDPlayer(), new Projector(), new TheaterLights(), new Screen() ); theatre.watchMovie("Inception"); theatre.endMovie(); } }
JdbcTemplate — Facade over raw JDBC (Connection, PreparedStatement, ResultSet, exception handling)java.net.URL — Facade over HTTP connection, socket, stream managementRestTemplate / WebClient — Facade over HTTP client complexitySession — Facade over SQL generation, connection pooling, caching// ❌ BREAKING — God Facade with business logic public void watchMovie(String movie) { // ❌ Facade doing business logic, not just orchestration if (movie.contains("adult")) { verifyAge(); chargeSubscription(); logAnalytics(); // wrong place! } lights.dim(10); // ... } // ✅ FIX — Facade only orchestrates, logic stays in subsystem public void watchMovie(String movie) { lights.dim(10); screen.down(); projector.on(); amp.on(); dvd.on(); dvd.play(movie); // purely orchestration } // ❌ BREAKING — swallowing exceptions public void watchMovie(String movie) { try { dvd.play(movie); } catch (Exception e) { // ❌ silent catch — client thinks movie is playing } } // ✅ FIX — wrap and rethrow public void watchMovie(String movie) { try { dvd.play(movie); } catch (DVDException e) { throw new TheatreException("Could not play movie", e); } } // ❌ BREAKING — bypassing Facade directly // client reaches into subsystem, defeats the pattern DVDPlayer dvd = theatre.getDVD(); // ❌ leaking subsystem reference dvd.play("raw call"); // ✅ FIX — package-private subsystem, no getters on Facade class DVDPlayer { // package-private — only Facade in same package can use void play(String m) { /* ... */ } }