Facade Pattern - Simplification d'interfaces complexes
Pattern structurel qui fournit une interface unifiée et simplifiée pour accéder à un ensemble de sous-systèmes complexes.
Mis à jour le 9 janvier 2026
Le pattern Facade est un design pattern structurel qui masque la complexité d'un système en fournissant une interface simplifiée. Il agit comme un point d'entrée unique qui coordonne les interactions entre plusieurs composants internes, réduisant ainsi le couplage et améliorant la maintenabilité du code.
Fondements
- Interface unifiée qui encapsule la complexité de multiples sous-systèmes
- Réduction du couplage entre le client et les composants internes
- Simplification de l'API publique en masquant les détails d'implémentation
- Point d'entrée centralisé facilitant l'utilisation et la documentation
Avantages
- Réduction drastique de la complexité pour les clients du système
- Meilleure testabilité grâce à l'isolation des dépendances
- Facilitation des évolutions internes sans impact sur les clients
- Documentation naturelle du flux métier principal
- Réduction du nombre de dépendances exposées publiquement
Exemple concret
Prenons l'exemple d'un système de e-commerce nécessitant la coordination de plusieurs services (inventaire, paiement, expédition) pour traiter une commande :
// Sous-systèmes complexes
class InventoryService {
checkStock(productId: string, quantity: number): boolean {
// Logique complexe de vérification
return true;
}
reserveItems(productId: string, quantity: number): string {
return `reservation-${Date.now()}`;
}
}
class PaymentService {
validateCard(cardNumber: string): boolean {
// Validation complexe
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 simplifiant l'orchestration
class OrderFacade {
constructor(
private inventory: InventoryService,
private payment: PaymentService,
private shipping: ShippingService
) {}
placeOrder(orderData: OrderRequest): OrderResult {
// 1. Vérifier disponibilité
if (!this.inventory.checkStock(orderData.productId, orderData.quantity)) {
throw new Error('Product out of stock');
}
// 2. Réserver les articles
const reservationId = this.inventory.reserveItems(
orderData.productId,
orderData.quantity
);
// 3. Calculer les frais de port
const shippingCost = this.shipping.calculateShipping(orderData.address);
const totalAmount = orderData.price * orderData.quantity + shippingCost;
// 4. Traiter le paiement
if (!this.payment.validateCard(orderData.cardNumber)) {
throw new Error('Invalid payment method');
}
const paymentId = this.payment.processPayment(
totalAmount,
orderData.cardToken
);
// 5. Planifier l'expédition
const shipmentId = this.shipping.scheduleDelivery(
paymentId,
orderData.address
);
return {
orderId: paymentId,
reservationId,
shipmentId,
total: totalAmount,
status: 'confirmed'
};
}
}
// Utilisation simplifiée pour le 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' }
});Mise en œuvre
- Identifier les sous-systèmes complexes nécessitant coordination
- Définir l'interface publique simplifiée (méthodes de haut niveau)
- Créer la classe Facade qui encapsule les dépendances internes
- Implémenter les méthodes de la facade en orchestrant les sous-systèmes
- Gérer les erreurs et cas limites de manière centralisée
- Documenter les flux métier principaux exposés par la facade
- Migrer progressivement les clients vers la nouvelle interface
Conseil professionnel
Ne créez pas de facades trop larges (God Object). Privilégiez plusieurs facades spécialisées par domaine métier plutôt qu'une seule facade géante. Chaque facade devrait avoir une responsabilité claire et cohérente.
Outils associés
- TypeScript interfaces pour définir les contrats de la facade
- Dependency Injection containers (InversifyJS, TSyringe) pour gérer les dépendances
- API Gateway patterns pour les architectures distribuées
- BFF (Backend For Frontend) pour créer des facades spécifiques par client
- Outils de documentation (TypeDoc, Swagger) pour exposer l'API simplifiée
Le pattern Facade représente un investissement stratégique dans la qualité architecturale. En réduisant la complexité perçue et en centralisant les flux métier critiques, il accélère le développement, facilite l'onboarding des nouveaux développeurs et réduit significativement les coûts de maintenance à long terme.
