image de chargement
Back to glossary

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:

order-facade.ts
// 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

  1. Identify complex subsystems requiring coordination
  2. Define the simplified public interface (high-level methods)
  3. Create the Facade class encapsulating internal dependencies
  4. Implement facade methods by orchestrating subsystems
  5. Handle errors and edge cases centrally
  6. Document main business flows exposed by the facade
  7. 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.

  • 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.

Themoneyisalreadyonthetable.

In 1 hour, discover exactly how much you're losing and how to recover it.