Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Зачем нужен адаптер?
Адаптер — это паттерн проектирования, который позволяет преобразовать интерфейс одного класса в интерфейс другого, который ожидает клиент. Адаптер создает "мост" между несовместимыми интерфейсами, делая их совместимыми без изменения исходного кода.
Основные проблемы, которые решает адаптер
Несовместимость интерфейсов — иногда нужно использовать класс или библиотеку, интерфейс которой не совпадает с тем, что ожидает твой код. Адаптер преобразует один интерфейс в другой.
Интеграция с внешними API — при работе с REST API, GraphQL или других внешних сервисов их ответы часто имеют структуру, отличную от той, которую использует приложение.
Переиспользование кода — позволяет использовать полезный код, который нельзя напрямую изменить (например, библиотека третьей стороны).
Практические примеры в Frontend
Пример 1: Адаптер для API
// API возвращает такую структуру
const apiResponse = {
user_id: 123,
first_name: "John",
last_name: "Doe",
email_address: "john@example.com"
};
// Но приложение ожидает такую
interface User {
id: number;
firstName: string;
lastName: string;
email: string;
}
// Адаптер преобразует API-ответ в нужный формат
const adaptUserFromAPI = (apiData: any): User => {
return {
id: apiData.user_id,
firstName: apiData.first_name,
lastName: apiData.last_name,
email: apiData.email_address
};
};
const user: User = adaptUserFromAPI(apiResponse);
Пример 2: Адаптер для работы с датами
// Разные форматы дат из разных API
const momentDate = moment("2024-01-15");
const dateObject = new Date("2024-01-15");
// Привести все к единому формату
interface AppDate {
timestamp: number;
iso: string;
formatted: string;
}
const adaptDate = (date: any): AppDate => {
const dateObj = date instanceof Date ? date : new Date(date);
return {
timestamp: dateObj.getTime(),
iso: dateObj.toISOString(),
formatted: dateObj.toLocaleDateString("ru-RU")
};
};
Пример 3: Адаптер для разных платежных систем
// Различные платежные API имеют разные интерфейсы
interface PaymentProvider {
processPayment(amount: number, currency: string): Promise<Transaction>;
}
// Адаптер для Stripe
class StripeAdapter implements PaymentProvider {
constructor(private stripeAPI: any) {}
async processPayment(amount: number, currency: string) {
const result = await this.stripeAPI.charges.create({
amount: amount * 100, // Stripe работает в центах
currency: currency.toLowerCase(),
source: "tok_visa"
});
return {
transactionId: result.id,
status: result.status === "succeeded" ? "success" : "failed"
};
}
}
// Адаптер для PayPal
class PayPalAdapter implements PaymentProvider {
constructor(private paypalAPI: any) {}
async processPayment(amount: number, currency: string) {
const result = await this.paypalAPI.executePayment({
value: amount.toString(),
currency_code: currency
});
return {
transactionId: result.id,
status: result.state === "approved" ? "success" : "failed"
};
}
}
Адаптер в React
// Кастомный хук как адаптер
function useApiUser(userId: number) {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(apiData => {
// Адаптируем API-ответ к формату приложения
const adaptedUser: User = {
id: apiData.user_id,
firstName: apiData.first_name,
lastName: apiData.last_name,
email: apiData.email_address
};
setUser(adaptedUser);
});
}, [userId]);
return user;
}
Преимущества адаптера
- Разделение ответственности — логика трансформации отделена от основного кода
- Переиспользуемость — адаптер можно использовать в разных местах
- Тестируемость — легко тестировать преобразования отдельно
- Гибкость — легко менять реализацию без изменения кода, который его использует
- Инкапсуляция — скрывает сложность преобразования внешних интерфейсов
Когда использовать адаптер
- Нужно интегрировать библиотеку с несовместимым интерфейсом
- Работаешь с API, возвращающим данные в неудобном формате
- Нужно унифицировать работу с несколькими похожими компонентами
- Хочешь изолировать код от изменений во внешних зависимостях
Адаптер — важный паттерн для создания гибких и поддерживаемых приложений, позволяя легко работать с несовместимыми интерфейсами и внешними API.