Коротка відповідь
middleAdapter — це паттерн, що дозволяє об’єднати інтерфейси несумісних класів. Він створює «обгортку», що перекладає виклики з одного інтерфейсу в потрібний. Наприклад, у TS: `class Adapter implements Target { constructor(private adaptee: Adaptee) {} request() { return this.adaptee.specificRequest(); }}`
Повне пояснення
1. Що це і навіщо
Adapter (Адаптер) — структурний патерн, що дозволяє класам з несумісними інтерфейсами працювати разом. Він використовується, коли існує готовий клас (Adaptee), але його інтерфейс не відповідає вимогам клієнта (Target).
2. Принцип роботи / алгоритм
Паттерн створює обгортку (Adapter), яка реалізує потрібний інтерфейс Target і в середині викликає методи Adaptee. Діаграма: Client → Target (Adapter) → Adaptee.
3. Реалізація (JS / TS)
- Базова реалізація
interface Target { request(): string; }
class Adaptee { specificRequest(): string { return "specific"; } }
class Adapter implements Target {
constructor(private adaptee: Adaptee) {}
request(): string { return this.adaptee.specificRequest(); }
}
- Веб‑dev приклад – адаптуємо сторонню бібліотеку, що повертає проміси, до інтерфейсу callback‑стилю.
class LegacyAPI { fetchData(cb: (data:any)=>void){ /* ... */ } }
class ModernAdapter implements Target {
constructor(private legacy: LegacyAPI) {}
request(): Promise<any> { return new Promise(resolve=>this.legacy.fetchData(resolve)); }
}
- Новачковий приклад – адаптуємо стару систему логування до нового.
class OldLogger { log(msg:string){ console.log('OLD:',msg); } }
class LoggerAdapter implements Target{ constructor(private old:OldLogger){} request(){ this.old.log('NEW'); }}
4. Тестування (Jest або Vitest)
test('Adapter forwards request', () => {
const adaptee = new Adaptee();
const adapter = new Adapter(adaptee);
expect(adapter.request()).toBe('specific');
});
5. Проблеми та edge cases
- Неправильне використання ролей – коли Adapter замість Target реалізує Adaptee.
- Зайва абстракція – створення Adapter для вже сумісного інтерфейсу.
- Cyclical dependencies – Adapter залежить від Target, а Target від Adapter.
- Плутанина з Decorator – обидва додають поведінку, але Adapter змінює інтерфейс.
- Performance‑пастки – надмірна кількість обгорток збільшує накладні витрати.
6. Оптимізація та продуктивність
Adapter додає один рівень виклику, що мінімально впливає на швидкість. Якщо Adapter створюється часто, варто кешувати його інстанси.
7. Без JS / архітектурні альтернативи
У чистій HTML/CSS можна «адаптувати» елементи через CSS‑префікси або Web Components, що виконують роль Adapter між стилями і поведінкою.
8. Cheatsheet + follow-up
- Cheatsheet: Adapter → Target (інтерфейс) + Adaptee (реалізація).
- Interview Q1: Як відрізнити Adapter від Decorator?
- Interview Q2: Які переваги має Adapter у мікросервісній архітектурі?