Вивчіть шаблон проєктування Adapter на реальних прикладах TypeScript. Навчіться поєднувати несумісні API, рефакторити застарілий код і будувати масштабовані системи.
January 7, 2026 (3mo ago)
Ваш путівник по шаблону проєктування Adapter у чистому коді
Вивчіть шаблон проєктування Adapter на реальних прикладах TypeScript. Навчіться поєднувати несумісні API, рефакторити застарілий код і будувати масштабовані системи.
← Back to blog
Title: Ваш путівник по шаблону проєктування Adapter у чистому коді Description: Вивчіть шаблон проєктування Adapter на реальних прикладах TypeScript. Навчіться поєднувати несумісні API, рефакторити застарілий код і будувати масштабовані системи. Tags: design pattern adapter, clean code, typescript, api integration, refactoring Content: Шаблон проєктування Adapter по суті є посередником. Уявіть його як перекладача, що дозволяє двом несумісним системам без проблем спілкуватися одна з одною. Уся суть — змусити існуючі класи співпрацювати, не чіпаючи їхній початковий вихідний код. Це програмний аналог мережевого адаптера для подорожей, що дозволяє підключити ваш канадський електроприлад до європейської розетки.
Цей шаблон — наріжний камінь чистого й підтримуваного коду, особливо коли ви намагаєтеся інтегрувати бібліотеку стороннього виробника або приборкати застарілу систему.1
Чому вашій кодовій базі потрібен шаблон Adapter

Уявіть: ви в Європі й намагаєтеся втиснути канадський ноутбук у розетку. Він просто не підходить. Ваш зарядний пристрій працює нормально, розетка працює нормально, але їхні інтерфейси повністю різні. Така сама проблема постійно виникає в розробці програмного забезпечення, коли нам потрібно, щоб дві системи, ніколи не призначені для спільної роботи, раптом почали взаємодіяти.
Ось тут і приходить шаблон Adapter. Це ваш універсальний «мережевий адаптер» для коду, який створює безшовний міст між невідповідними компонентами.
Подолання розриву в сучасній розробці
Сьогодні ми рідко будуємо все з нуля. Ми збираємо рішення з бібліотек сторонніх розробників, зовнішніх API та застарілих систем. Це прискорює доставку, але створює несумісні інтерфейси та спокусу робити тимчасові винятки, що призводять до довгострокових проблем:
- Дублювання коду: одна й та сама логіка перетворення розосереджується по додатку.
- Висока зв'язаність: бізнес-логіка переплітається з деталями зовнішніх сервісів.
- Зростання технічного боргу: кожна зміна API викликає полювання за крихкою інтеграційною логікою.
Шаблон Adapter дає вам окремий клас-адаптер, який обробляє перетворення в одному місці, захищаючи ядро вашої аплікації та полегшуючи підтримку інтеграцій. Такий підхід поширений у командах, що віддають перевагу модульній архітектурі та поступовій модернізації.2
Шаблон Adapter — це не просто хак, щоб змусити щось працювати. Він захищає простоту та цілісність вашої основної логіки, екрануючи її від хаотичних деталей зовнішніх систем.
Адаптери сприяють чистому та масштабованому коду
Адаптер — це стратегія побудови гнучкої архітектури, яка може змінюватися без повного переписування. Ви можете замінювати сервіси або поетапно виводити застарілі системи, додаючи або замінюючи адаптери замість того, щоб чіпати код клієнта. Така стабільність прискорює розробку фіч і знижує ризики інтеграції.2
Як шаблон Adapter насправді працює
У своїй основі шаблон створює чітке розділення між частинами системи, щоб вони могли розвиватися незалежно. Чотири гравці роблять цей шаблон легким для розуміння:
- Клієнт: код, якому потрібно виконати дію й який очікує простий, стабільний інтерфейс.
- Ціль (Target): чистий інтерфейс, яким користується Клієнт.
- Адаптований клас (Adaptee): існуючий компонент з несумісним інтерфейсом (часто незмінний).
- Адаптер: реалізує Ціль і перекладає виклики до Адаптованого класу.

Клієнт завжди говорить тільки з Ціллю; Адаптер тихо перекладає для Адаптованого класу. Такий дизайн добре узгоджується з принципом відкритості/закритості: ви можете інтегрувати новий сервіс, написавши новий адаптер, при цьому не торкаючись існуючого коду клієнтів.1
Головна мета шаблону Adapter — перетворити інтерфейс класу в інший інтерфейс, який очікують клієнти. Адаптер дозволяє класам працювати разом, які б інакше не змогли через несумісні інтерфейси.3
Побудова адаптерів в TypeScript з реальними прикладами

Нижче два практичні приклади на TypeScript, що відображають поширені реальні проблеми: адаптація застарілого XML API і стандартизація стороннього платіжного шлюзу.
Приклад 1: Адаптація застарілого XML API до JSON
Сценарій: ваш сучасний React-фронтенд очікує JSON, але єдиним джерелом даних є застарілий сервіс, що повертає XML. Клієнт має використовувати чистий інтерфейс IUserService; LegacyUserService працює з XML. Адаптер їх зв'язує.
The Incompatible Adaptee
// Adaptee: The old service with an incompatible interface
class LegacyUserService {
fetchUsersXML(): string {
return `
<users>
<user id="1">
<name>Alice</name>
<email>alice@example.com</email>
</user>
<user id="2">
<name>Bob</name>
<email>bob@example.com</email>
</user>
</users>
`;
}
}
The Target Interface and Adapter
interface IUser {
id: number;
name: string;
email: string;
}
interface IUserService {
getUsers(): Promise<IUser[]>;
}
class UserServiceAdapter implements IUserService {
private adaptee: LegacyUserService;
constructor(legacyService: LegacyUserService) {
this.adaptee = legacyService;
}
async getUsers(): Promise<IUser[]> {
const xmlData = this.adaptee.fetchUsersXML();
// Use a robust XML parser in production (e.g., xml2js).
console.log("Translating XML to JSON...");
return [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
];
}
}
З цим адаптером код клієнта говорить з IUserService і залишається неприв'язаний до XML.
Приклад 2: Стандартизація стороннього платіжного шлюзу
Сценарій: ваш додаток використовує стандартний інтерфейс IPaymentProcessor, але шлюз PayWizard має методи на зразок startTransaction і verifyPaymentStatus. Адаптер зіставляє ваші стандартні виклики з API PayWizard.
The Inconsistent Adaptee
class PayWizard {
startTransaction(amount: number, cardDetails: string): string {
console.log(`PayWizard: Initiating transaction for $${amount}.`);
const transactionId = "pw_" + Math.random().toString(36).substr(2, 9);
return transactionId;
}
verifyPaymentStatus(transactionId: string): boolean {
console.log(`PayWizard: Verifying status for ${transactionId}.`);
return true;
}
}
The Target Interface and Adapter
interface IPaymentProcessor {
processPayment(amount: number, cardInfo: string): Promise<string>;
checkStatus(id: string): Promise<boolean>;
}
class PayWizardAdapter implements IPaymentProcessor {
private payWizard: PayWizard;
constructor() {
this.payWizard = new PayWizard();
}
async processPayment(amount: number, cardInfo: string): Promise<string> {
console.log("Adapter: Translating 'processPayment' to 'startTransaction'.");
return this.payWizard.startTransaction(amount, cardInfo);
}
async checkStatus(id: string): Promise<boolean> {
console.log("Adapter: Translating 'checkStatus' to 'verifyPaymentStatus'.");
return this.payWizard.verifyPaymentStatus(id);
}
}
Використання адаптерів підтримує код вашого додатку чистим і послідовним серед різних провайдерів.
Рефакторинг застарілого коду за допомогою адаптерів

Кожен проєкт рано чи пізно стикається із застарілим кодом. Шаблон Adapter дозволяє уникнути ризикових великих переписувань, обернувши старі системи сучасним цільовим інтерфейсом і поетапно мігруючи код клієнта. Такий підхід знижує ризики і підтримує контрольований план модернізації.2
Покроковий план міграції
- Визначте бажаний цільовий інтерфейс.
- Створіть клас-адаптер, який реалізує цей інтерфейс і приймає застарілий Адаптований клас.
- Реалізуйте логіку перетворення всередині адаптера.
- Поетапно мігруйте код клієнта на використання адаптера.
Прискорення рефакторингу за допомогою AI
Сучасні інструменти ШІ можуть пришвидшити генерацію шаблонного коду, дозволяючи зосередитися на критичній логіці відображення, але архітектурні рішення залишаються відповідальністю команди. Використовуйте інструменти для створення каркасу адаптерів, а потім пишіть тести, що перевіряють відповідність відображень.
Використання адаптера — це не просто тимчасове виправлення; це стратегічна інвестиція в архітектурне здоров'я, що дозволяє поступову модернізацію.2
Вибір між Adapter і іншими шаблонами
Правильний вибір шаблону має значення. Adapter, Decorator, Proxy і Façade можуть виглядати схоже, але виконують різні функції. Використовуйте Adapter для зміни інтерфейсів; Decorator — для додавання поведінки; Proxy — для контролю доступу; Façade — для спрощення складних підсистем.
Adapter проти Decorator
Adapter перекладає інтерфейс. Decorator додає обов'язки, зберігаючи оригінальний інтерфейс.
Adapter проти Proxy
Proxy зберігає той самий інтерфейс і контролює доступ або додає лінивe ініціалізування, кешування чи логування. Adapter змінює інтерфейс, щоб клієнт міг використовувати інакше несумісний компонент.
Adapter проти Façade
Façade спрощує підсистему за допомогою єдиного інтерфейсу. Adapter зосереджується на перетворенні інтерфейсу одного об'єкта, щоб два компоненти могли взаємодіяти.
| Pattern | Primary Intent | When to Use |
|---|---|---|
| Adapter | Convert one interface to another | When an existing class must work with an incompatible client. |
| Decorator | Add responsibilities | When you want to extend behavior dynamically. |
| Proxy | Control access | When you need lazy loading, access control, or logging. |
| Façade | Simplify a subsystem | When you want a single entry point to complex behavior. |
Впровадження шаблону Adapter у вашій команді
Щоб уникнути надмірного використання, встановіть чіткі правила для створення адаптерів:
- Документація: кожен адаптер має мати README, де вказані Адаптований клас, Цільовий інтерфейс і відображення.
- Тестування: вимагаються юніт-тести, що підтверджують логіку перетворення.
- Моніторинг продуктивності: робіть бенчмарки критичних адаптерів, якщо вони знаходяться на гарячих шляхах.
Додайте автоматичні перевірки в CI, щоб забезпечити дотримання цих правил і зберегти узгодженість адаптерів у кодовій базі. Надайте приклади та шаблони в внутрішній документації або дайте посилання на керівництва, як-от modernizing legacy systems.
Є питання? Поговорімо про адаптери
Q&A
Q: Коли адаптер кращий за повне переписування?
A: Використовуйте адаптер, коли наявний компонент працює, але його інтерфейс не відповідає вашим потребам — особливо для стабільних застарілих систем або сторонніх API, якими ви не керуєте. Якщо компонент має баги або йому бракує необхідних функцій, може знадобитись переписування.
Q: Чи додають адаптери помітні витрати на продуктивність?
A: Адаптери додають мілку накладну витрату — додатковий виклик методу або крок конвертації — але в більшості бізнес-додатків це несуттєво порівняно з мережевими або I/O-витратами. Для систем, чутливих до затримок, проведіть бенчмарки адаптера.
Q: Як моя команда має тестувати адаптери?
A: Пишіть юніт-тести, що зосереджуються на відображеннях між Ціллю та Адаптованим класом. Мокуйте Адаптований клас там, де це доречно, і включайте інтеграційні тести, щоб переконатися, що адаптер правильно поводиться з реальною залежністю.
Maintain all markdown formatting, links, and code blocks exactly as they are.
ШІ пише код.Ви робите його довговічним.
В епоху прискорення ШІ чистий код — це не просто хороша практика — це різниця між системами, які масштабуються, та кодовими базами, які руйнуються під власною вагою.