You check into a hotel. You want a room sorted, a taxi booked, dinner reserved, and a wake-up call.
Do you hunt down the housekeeping department, then the transport desk, then the kitchen, then the operator, one at a time? No. You call reception and say "sort all this out." Reception knows who to call behind the scenes. You talk to one person instead of five.
That's the Facade pattern: one simple front door that hides a messy, complicated system behind it.
The problem: the caller has to know everything
Say placing an order actually involves four subsystems, in a specific order:
// Every caller has to know ALL of this, in the RIGHT sequence
var inventory = new InventoryService();
if (!inventory.CheckStock(itemId)) return;
inventory.Reserve(itemId);
var payment = new PaymentService();
payment.Charge(customerId, amount);
var shipping = new ShippingService();
var trackingId = shipping.Schedule(itemId, address);
var notifier = new EmailService();
notifier.Send(customerId, $"Order placed! Track: {trackingId}");
Every place that needs to place an order repeats all of this — every service, every method, the exact sequence. Change the steps once and you're editing it everywhere.
The Facade
Wrap the whole mess behind one class with one simple method:
public class OrderFacade
{
private readonly InventoryService _inventory = new();
private readonly PaymentService _payment = new();
private readonly ShippingService _shipping = new();
private readonly EmailService _email = new();
// one simple door
public void PlaceOrder(int customerId, int itemId, decimal amount, string address)
{
if (!_inventory.CheckStock(itemId)) throw new Exception("Out of stock");
_inventory.Reserve(itemId);
_payment.Charge(customerId, amount);
var trackingId = _shipping.Schedule(itemId, address);
_email.Send(customerId, $"Order placed! Track: {trackingId}");
}
}
Now the caller's entire job is one line:
var order = new OrderFacade();
order.PlaceOrder(customerId: 1, itemId: 42, amount: 999, address: "Bengaluru");
The caller has no idea there are four services and a specific sequence behind it — exactly like the hotel guest has no idea reception rang four departments.
The key insight
The subsystems still exist and still work as before. The Facade doesn't remove complexity — it hides it behind a clean entry point. And it isn't a wall: if some advanced caller genuinely needs PaymentService directly, it's still there. The Facade is a convenience, not a lockdown.
Facade vs Adapter — both wrap, different purpose
This is the confusion worth clearing up:
- Adapter wraps one thing to change its shape so it fits somewhere it didn't before. Purpose: compatibility.
- Facade wraps many things to give one simple entry point. Purpose: simplicity.
Adapter is one object with a different shape. Facade is many objects behind one easy door.
Where you've already seen it
HttpClient is a facade. Behind that one friendly class sits DNS resolution, sockets, TLS handshakes, and connection pooling. You just call GetAsync() and none of that surfaces. Most well-designed "Service" classes in an app are facades too — a clean method on top of repositories, validators, and mappers.
One line to remember
Facade = hotel reception. One simple door in front; it coordinates the messy departments behind the scenes.
Part 6 of a series on must-know design patterns in C#, explained the simple way. Earlier parts covered Singleton, Factory Method, Builder, Adapter, and Decorator. Next up: Proxy — the bodyguard pattern.
Top comments (0)