Как ответить
На практике я использую Фасад для упрощения работы со сложными подсистемами, где клиенту не нужно знать внутренние детали. Например, в одном проекте мы интегрировали платёжный шлюз с тремя провайдерами — PayPal, Stripe и локальный сервис. Вместо того чтобы заставлять бизнес-логику разбираться с разными API, форматами ответов и обработкой ошибок, я написал единый фасад — PaymentService.
Вот как это выглядит в коде:
class PaymentService {
private paypal: PayPalAPI;
private stripe: StripeAPI;
private local: LocalGateway;
constructor() {
this.paypal = new PayPalAPI();
this.stripe = new StripeAPI();
this.local = new LocalGateway();
}
async charge(amount: number, currency: string, method: string): Promise<PaymentResult> {
try {
if (method === 'paypal') {
return this.paypal.createPayment(amount, currency);
} else if (method === 'stripe') {
return this.stripe.charge(amount, currency);
} else {
return this.local.process(amount, currency);
}
} catch (error) {
// Единая обработка ошибок и логирование
return { success: false, error: this.formatError(error) };
}
}
private formatError(error: any): string {
// Нормализация ошибок от разных провайдеров
return error.message || 'Payment failed';
}
}Клиентский код теперь выглядит просто: paymentService.charge(100, 'USD', 'stripe'). Если мы добавляем четвёртого провайдера, меняется только фасад, а не десятки мест, где вызывается оплата. Ещё один пример — в проекте с микросервисами мы сделали фасад для агрегации данных с трёх сервисов (пользователи, заказы, инвентарь) в один ответ для фронтенда. Это сократило количество запросов с 3 до 1 и упростило тестирование.
Важный нюанс: фасад не должен быть божественным объектом. Я слежу, чтобы он не обрастал методами, которые дублируют логику подсистем. Если методов становится больше 5–7, разбиваю на несколько специализированных фасадов. Например, отдельный фасад для чтения данных и отдельный для записи.
Из минусов: фасад может скрывать гибкость. Если клиенту вдруг понадобится кастомная настройка, которую фасад не предоставляет, приходится либо расширять фасад, либо давать доступ к подсистеме напрямую — это компромисс. В нашем платёжном шлюзе мы добавили метод getProvider(name), который возвращает конкретный API для редких кейсов.