Back to All Design Patterns
Pattern 7 of 22
Structural PatternBEGINNER6 min deep dive
Facade Pattern Pattern
Provides a simplified, unified interface to a complex subsystem of classes, libraries, or frameworks.
Real-World Mental Model / Metaphor:
A hotel concierge. You tell the concierge: 'Book me dinner and a theater ticket'. The concierge coordinates with restaurants, taxi drivers, and ticket vendors behind the scenes.
Interactive Runtime Simulator
Test and tweak inputs dynamicallyInteractive Facade Pattern SimulatorLIVE PLAYGROUND
Interact with the controls below to see how this design pattern executes in memory at runtime.
Configure Chain Handlers (Toggle Failures):
CHAIN PIPELINE STATUS
Step 1: AuthHandler.check() -> PASSED
Step 2: RateLimitHandler.check() -> PASSED
Step 3: PayloadGuard.check() -> PASSED
The Problem It Solves
Client code getting tangled in dozens of interdependent subsystem classes, making it difficult to maintain and tightly coupling the client to low-level implementation details.
The Architectural Solution
Introduce a Facade class that encapsulates subsystem coordination behind simple 1-line public methods.
Pattern Structure & Participants
| Participant | Role & Responsibility | Type |
|---|---|---|
| Facade | Provides simple methods like bookOrder() or convertVideo() | class |
| Subsystem Classes (A, B, C, D) | Complex underlying engines | class |
| Client | Interacts ONLY with the Facade | client |
Collaboration Rules:
- Client calls facade.checkout(cart)
- Facade orchestrates Payment, Inventory, and Shipping engines in order
Production Code Implementation
Facade Pattern.java
// Complex Subsystems
public class InventoryService {
public boolean checkStock(String productId) { return true; }
public void deduct(String productId) { System.out.println("Stock deducted"); }
}
public class PaymentGateway {
public boolean charge(String userId, double amount) {
System.out.println("Charged $" + amount + " to user: " + userId);
return true;
}
}
public class NotificationService {
public void sendOrderConfirmation(String userId) {
System.out.println("Email receipt sent to " + userId);
}
}
// Clean Production Facade
public class OrderCheckoutFacade {
private final InventoryService inventory = new InventoryService();
private final PaymentGateway payment = new PaymentGateway();
private final NotificationService notifier = new NotificationService();
public boolean placeOrder(String userId, String productId, double price) {
if (!inventory.checkStock(productId)) return false;
boolean charged = payment.charge(userId, price);
if (!charged) return false;
inventory.deduct(productId);
notifier.sendOrderConfirmation(userId);
return true; // Simplified 1-line call for the client!
}
} When to Use:
- •To provide a simple, default interface to a complex subsystem.
- •To decouple client code from the inner workings of third-party libraries.
- •To structure subsystems into distinct layered architectural tiers.
When to Avoid (Anti-Pattern):
- •When client code genuinely needs low-level fine-grained control over individual subsystem steps.
Staff Engineering Interview Insights & Gotchas
- Contrast Facade vs Adapter: Facade defines a brand new simplified interface; Adapter matches an existing incompatible interface.
- Explain how Microservice API Gateways (BFF pattern) are essentially distributed Facades.