10. Facade
The Facade pattern provides a unified, simplified interface to a set of interfaces in a subsystem. It defines a higher-level interface that makes the subsystem easier to use, hiding the complexity of multiple collaborating classes.
Intent and Motivation
Intent: 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.
Motivation: A home theater subsystem involves Amplifier, DVDPlayer, Projector, Screen, and Lights — each with dozens of methods. Watching a movie requires a precise sequence: dim lights, lower screen, turn on projector, set input, play DVD. Clients should not orchestrate this every time. A HomeTheaterFacade.watchMovie() encapsulates the ritual. The facade does not prevent direct subsystem access for power users; it simply offers a convenient entry point.
Facades are the most common pattern in practice — service layers, API gateways, and SDK entry points are all facades.
Structure (UML-like)
┌──────────┐
│ Client │
└────┬─────┘
│ uses simplified API
▼
┌──────────────┐ coordinates ┌─────────────────────────┐
│ Facade │ ───────────────────────► │ Subsystem │
├──────────────┤ │ ┌─────┐ ┌─────┐ ┌────┐│
│ + operation()│ │ │Class│ │Class│ │Cls ││
└──────────────┘ │ │ A │ │ B │ │ C ││
│ └─────┘ └─────┘ └────┘│
└─────────────────────────┘
Participants:
- Facade — knows which subsystem classes are responsible for a request; delegates to them.
- Subsystem classes — implement subsystem functionality; can be used directly or through the facade.
- Client — communicates with the subsystem through the facade (or directly for advanced use).
Java Example
// Subsystem classes
class CPU {
void freeze() { System.out.println("CPU freeze"); }
void jump(long address) { System.out.println("CPU jump to " + address); }
void execute() { System.out.println("CPU execute"); }
}
class Memory {
void load(long address, byte[] data) {
System.out.println("Memory load at " + address);
}
}
class HardDrive {
byte[] read(long lba, int size) {
System.out.println("HardDrive read sector " + lba);
return new byte[size];
}
}
// Facade
class ComputerFacade {
private final CPU cpu = new CPU();
private final Memory memory = new Memory();
private final HardDrive hd = new HardDrive();
void start() {
cpu.freeze();
memory.load(0, hd.read(0, 1024));
cpu.jump(0);
cpu.execute();
}
}
// Client — one line instead of orchestrating three subsystems
new ComputerFacade().start();
JavaScript Example
// Subsystem modules
const authService = {
login(user, pass) { console.log(`Auth: ${user}`); return { token: 'jwt-abc' }; }
};
const cartService = {
addItem(token, item) { console.log(`Cart: added ${item}`); },
getTotal(token) { return 99.99; }
};
const paymentService = {
charge(token, amount) { console.log(`Payment: charged $${amount}`); }
};
const emailService = {
sendConfirmation(user, amount) { console.log(`Email: receipt to ${user}`); }
};
// Facade
const checkoutFacade = {
completePurchase(username, password, items) {
const { token } = authService.login(username, password);
items.forEach(item => cartService.addItem(token, item));
const total = cartService.getTotal(token);
paymentService.charge(token, total);
emailService.sendConfirmation(username, total);
return { success: true, total };
}
};
checkoutFacade.completePurchase('alice', 'secret', ['laptop', 'mouse']);
Real-World Use Cases
| Framework / System | Usage |
|---|---|
Spring @Service classes |
Service layer facades coordinate repositories, caches, and messaging. |
| SLF4J | Simple logging facade hiding Logback/Log4j complexity. |
| AWS SDK | High-level S3Client.putObject() hides HTTP signing, retries, and serialization. |
| jQuery | $('#el').fadeIn() facades over verbose DOM APIs. |
| Express app structure | Route handlers facade over database, cache, and auth subsystems. |
Hibernate Session |
Facades over JDBC, connection pooling, and SQL generation. |
Pros and Cons
| Pros | Cons |
|---|---|
| Simplifies complex subsystem usage for common workflows | Facade can become a “god class” accumulating too much logic |
| Decouples clients from subsystem components | Hides subsystem flexibility — power users may need direct access |
| Promotes layering and clean architecture boundaries | Changes in subsystem may require facade updates |
| Does not prevent direct subsystem access when needed | Can mask performance issues by bundling expensive operations |
| Improves testability by mocking one facade instead of many classes | Multiple facades for the same subsystem can cause confusion |
When to Use vs When NOT to Use
Use when:
- A complex subsystem needs a simple, high-level entry point.
- You want to decouple clients from subsystem implementation details.
- You are layering a system (presentation → business → data access).
- Many clients use the same orchestration sequence repeatedly.
Do NOT use when:
- The subsystem is already simple — a facade adds unnecessary indirection.
- Clients need fine-grained control over every subsystem operation.
- You are converting incompatible interfaces (use Adapter).
- The facade grows so large it becomes the entire application (refactor into smaller services).
Common Mistakes
- Facade with business logic — facades should orchestrate, not implement domain rules (move logic to domain services).
- One mega-facade for the entire application — split by bounded context or use case.
- Preventing direct subsystem access — facades should simplify, not lock down.
- Confusing Facade with Mediator — Facade is unidirectional (client → subsystem); Mediator handles bidirectional colleague communication.
- Returning subsystem objects from facade methods — leaks abstraction; return DTOs or primitives.
Related Patterns
- Adapter — wraps one object to match an interface; Facade simplifies many objects into one interface.
- Mediator — colleagues communicate through mediator; Facade is a one-way simplification layer.
- Abstract Factory — can provide subsystem objects that a Facade coordinates.
- Singleton — facades are often singletons because one entry point per subsystem is typical.
- API Gateway (microservices) — architectural application of Facade at the network level.