Design PatternsStructural

Facade

Provide a unified, simplified interface to a complex subsystem.

3 min readDesigns · LLD & Patterns

Intent

Hide the complexity of a subsystem behind a single, narrow API.

Use when:

  • A subsystem has many classes and the typical use case touches several of them.
  • You want to reduce coupling between callers and the subsystem internals.
  • You're integrating a complex library and most callers only need a fraction of it.

Real-world Analogy

A car's ignition: turn the key (one action), and behind the scenes — the starter motor engages, the fuel pump primes, the spark plugs fire, the alternator kicks in. The driver doesn't care about any of that. The key is the facade.


Structure

StructureClass diagram

Example: Order Placement

Without facade — caller orchestrates everything:

class WebController {
    void placeOrder(OrderRequest req) {
        Inventory inv = new Inventory();
        if (!inv.reserve(req.items)) throw new OutOfStockException();

        Pricing pricing = new Pricing();
        Money total = pricing.calculate(req.items, req.coupon);

        Payment pay = new Payment();
        if (!pay.charge(req.card, total)) {
            inv.release(req.items);
            throw new PaymentFailedException();
        }

        Shipping ship = new Shipping();
        ship.schedule(req.address, req.items);

        Email email = new Email();
        email.send(req.userEmail, "Order confirmed!");
    }
}

The controller knows about 5 subsystems and the order in which to call them.

With facade

public class OrderFacade {
    private final Inventory inventory;
    private final Pricing pricing;
    private final Payment payment;
    private final Shipping shipping;
    private final Email email;

    public OrderFacade(Inventory i, Pricing p, Payment pay, Shipping s, Email e) {
        this.inventory = i; this.pricing = p; this.payment = pay;
        this.shipping = s; this.email = e;
    }

    public OrderResult placeOrder(OrderRequest req) {
        if (!inventory.reserve(req.items)) return OrderResult.outOfStock();

        Money total = pricing.calculate(req.items, req.coupon);

        if (!payment.charge(req.card, total)) {
            inventory.release(req.items);
            return OrderResult.paymentFailed();
        }

        shipping.schedule(req.address, req.items);
        email.send(req.userEmail, "Order confirmed!");

        return OrderResult.success();
    }
}

// Caller
class WebController {
    private final OrderFacade orders;
    void placeOrder(OrderRequest req) { orders.placeOrder(req); }
}

Now the caller depends on one thing. Adding a fraud-check step happens inside the facade; no caller changes.


Facade vs Mediator vs Adapter

PatternIntentNumber of subsystems
FacadeSimplify interface to a subsystemOne subsystem (usually)
MediatorCoordinate communication between peersMany peers, all known
AdapterMake one interface match anotherOne thing being adapted

A facade is mostly outbound (hides callees from callers). A mediator is bidirectional (peers don't know each other; they all talk to the mediator).


When not to Use Facade

  • The subsystem is already simple — adding a layer adds noise without simplification.
  • Callers actually need fine-grained access — a facade locks them out of useful operations.
  • You're building a "god object" — if the facade has 50 methods, it's not really a facade anymore.

Real-world Examples

Use caseWhat it hides
JdbcTemplate (Spring)JDBC's connection / statement / result set boilerplate
RestTemplate, WebClientHTTP client setup, headers, deserialization
Logging frameworks (SLF4J)Multiple backends behind one API
java.util.logging.LoggerFile handles, formatters, levels
Stripe SDK Charge.create(...)API auth, retries, JSON serialization

Trade-offs

✅ Pros:

  • Decouples callers from subsystem internals
  • Simplifies the common case
  • Single place for cross-cutting concerns (logging, transactions)

❌ Cons:

  • Can become a god class if it grows unchecked
  • Hides power — advanced users may need to bypass it
  • Risk of leaky abstraction when subsystem details escape through return types

Interview Tips

  • Mention facade when the interviewer says "provide a clean API to ..." or "simplify usage of ...".
  • Distinguish from mediator: facade hides a subsystem from outside; mediator coordinates among inside peers.
  • If asked "should this be one facade or multiple?" — split by use case (OrderFacade, RefundFacade) rather than one mega-class.

Finished reading?

Mark it done to track your progress in Designs.