Facade Pattern - Simplifying Complex Interfaces
Structural pattern that provides a unified, simplified interface to access a set of complex subsystems.
Updated on January 9, 2026
The Facade pattern is a structural design pattern that hides system complexity by providing a simplified interface. It acts as a single entry point that coordinates interactions between multiple internal components, reducing coupling and improving code maintainability.
Fundamentals
- Unified interface that encapsulates the complexity of multiple subsystems
- Reduced coupling between client and internal components
- Simplified public API by hiding implementation details
- Centralized entry point facilitating usage and documentation
Benefits
- Drastic reduction in complexity for system clients
- Improved testability through dependency isolation
- Easier internal evolution without impacting clients
- Natural documentation of main business flows
- Reduced number of publicly exposed dependencies
Practical Example
Consider an e-commerce system requiring coordination of multiple services (inventory, payment, shipping) to process an order:
// Complex subsystems
class InventoryService {
checkStock(productId: string, quantity: number): boolean {
// Complex verification logic
return true;
}
reserveItems(productId: string, quantity: number): string {
return `reservation-${Date.now()}`;
}
}
class PaymentService {
validateCard(cardNumber: string): boolean {
// Complex validation
return true;
}
processPayment(amount: number, cardToken: string): string {
return `payment-${Date.now()}`;
}
}
class ShippingService {
calculateShipping(address: Address): number {
return 9.99;
}
scheduleDelivery(orderId: string, address: Address): string {
return `shipment-${Date.now()}`;
}
}
// Facade simplifying orchestration
class OrderFacade {
constructor(
private inventory: InventoryService,
private payment: PaymentService,
private shipping: ShippingService
) {}
placeOrder(orderData: OrderRequest): OrderResult {
// 1. Check availability
if (!this.inventory.checkStock(orderData.productId, orderData.quantity)) {
throw new Error('Product out of stock');
}
// 2. Reserve items
const reservationId = this.inventory.reserveItems(
orderData.productId,
orderData.quantity
);
// 3. Calculate shipping
const shippingCost = this.shipping.calculateShipping(orderData.address);
const totalAmount = orderData.price * orderData.quantity + shippingCost;
// 4. Process payment
if (!this.payment.validateCard(orderData.cardNumber)) {
throw new Error('Invalid payment method');
}
const paymentId = this.payment.processPayment(
totalAmount,
orderData.cardToken
);
// 5. Schedule shipment
const shipmentId = this.shipping.scheduleDelivery(
paymentId,
orderData.address
);
return {
orderId: paymentId,
reservationId,
shipmentId,
total: totalAmount,
status: 'confirmed'
};
}
}
// Simplified usage for client
const orderFacade = new OrderFacade(
new InventoryService(),
new PaymentService(),
new ShippingService()
);
const result = orderFacade.placeOrder({
productId: 'PROD-123',
quantity: 2,
price: 49.99,
cardNumber: '4111111111111111',
cardToken: 'tok_visa',
address: { street: '123 Main St', city: 'Paris', zip: '75001' }
});Implementation
- Identify complex subsystems requiring coordination
- Define the simplified public interface (high-level methods)
- Create the Facade class encapsulating internal dependencies
- Implement facade methods by orchestrating subsystems
- Handle errors and edge cases centrally
- Document main business flows exposed by the facade
- Progressively migrate clients to the new interface
Professional Tip
Avoid creating overly broad facades (God Object). Prefer multiple specialized facades per business domain rather than a single giant facade. Each facade should have a clear and cohesive responsibility.
Related Tools
- TypeScript interfaces to define facade contracts
- Dependency Injection containers (InversifyJS, TSyringe) for managing dependencies
- API Gateway patterns for distributed architectures
- BFF (Backend For Frontend) to create client-specific facades
- Documentation tools (TypeDoc, Swagger) to expose the simplified API
The Facade pattern represents a strategic investment in architectural quality. By reducing perceived complexity and centralizing critical business flows, it accelerates development, facilitates developer onboarding, and significantly reduces long-term maintenance costs.
