Ответ
Adapter (Адаптер) — это структурный паттерн, который позволяет объектам с несовместимыми интерфейсами работать вместе. Он выступает в роли "переводчика" или "прослойки" между клиентским кодом и сторонним сервисом/библиотекой/устаревшим классом.
Типичные ситуации для применения:
- Интеграция стороннего компонента, интерфейс которого не соответствует ожиданиям вашей системы.
- Работа с устаревшим кодом (legacy), который невозможно или нецелесообразно изменять, но нужно использовать в новой архитектуре.
- Унификация работы с несколькими классами, имеющими разную функциональность, но решающими схожую задачу.
Пример: Интеграция платёжной системы со странным API в вашу систему, ожидающую стандартный интерфейс IPaymentProcessor.
// 1. Интерфейс, который ожидает наша система (Target).
interface IPaymentProcessor {
void authorize(double amount);
void capture(String transactionId);
}
// 2. Сторонний класс с несовместимым интерфейсом (Adaptee).
class WeirdPaymentGateway {
public void authPayment(double amt, String currency) { /* ... */ }
public String completeAuth(String authCode) { /* ... */ return "TXN-123"; }
}
// 3. Адаптер, реализующий целевой интерфейс и оборачивающий сторонний класс.
class WeirdPaymentAdapter implements IPaymentProcessor {
private WeirdPaymentGateway gateway;
private String lastAuthCode;
public WeirdPaymentAdapter(WeirdPaymentGateway gateway) {
this.gateway = gateway;
}
@Override
public void authorize(double amount) {
// Адаптер преобразует вызов нашего метода в вызов метода стороннего класса.
gateway.authPayment(amount, "USD");
lastAuthCode = "AUTH_CODE_XYZ"; // Симулируем получение кода
}
@Override
public void capture(String transactionId) {
// Преобразуем параметры и вызов.
String result = gateway.completeAuth(lastAuthCode);
System.out.println("Captured via adapter. Transaction: " + result);
}
}
// 4. Клиентский код работает только с целевым интерфейсом.
public class Main {
public static void main(String[] args) {
IPaymentProcessor processor = new WeirdPaymentAdapter(new WeirdPaymentGateway());
processor.authorize(100.0); // Клиент не знает про WeirdPaymentGateway
processor.capture("some-id");
}
}
Итог: Адаптер не добавляет новой функциональности, он только преобразует один интерфейс в другой, обеспечивая совместимость.
Ответ 18+ 🔞
Слушай, я тут на днях вникал в этот ваш паттерн «Адаптер». Ну, ёпта, классика жанра, как старый добрый переходник для розетки. Представь: купил ты на алиэкспрессе крутую китайскую гирлянду, а вилка у неё — какая-то пизда с ушами, три квадратных штыря. И ты стоишь с этой хуйней перед нашей родной розеткой, и волнение ебать — как это всё соединить? Вот адаптер — он и есть эта самая переходная хуйня, которая позволяет твоей новой гирлянде засветиться в старой системе.
Короче, адаптер — это такой структурный паттерн, который заставляет объекты с абсолютно разными, несовместимыми интерфейсами работать вместе. Он как переводчик-синхронист на переговорах между двумя упрямыми начальниками, которые друг друга нахуй посылают.
Когда это нужно, спросишь? Да элементарно:
- Подключаешь какую-то стороннюю библиотеку или сервис, который написан каким-то пидарасом шерстяным, у которого свои понятия о красоте API.
- Работаешь с легаси-кодом, древним и страшным, который трогать страшно, но использовать надо. Типа дедушкиного мотоцикла, который заводится с пинка, но жрёт бензина дохуя.
- Хочешь привести к общему знаменателю кучу разных классов, которые делают одно и то же, но называют это разными словами.
Смотри, вот живой пример, чтобы совсем понятно стало. Допустим, вся твоя система заточена под красивый, стандартный интерфейс для платежей.
// 1. Это наш родной, понятный интерфейс (Цель). Его ждёт вся система.
interface IPaymentProcessor {
void authorize(double amount);
void capture(String transactionId);
}
А тут ты решил подключить новую платёжку «Рога и копыта». А её разработчики, видимо, с луны свалились, потому что их API — это просто ядрёна вошь.
// 2. Сторонний класс с ебанутым интерфейсом (Адаптируемый).
class WeirdPaymentGateway {
public void authPayment(double amt, String currency) { /* ... */ }
public String completeAuth(String authCode) { /* ... */ return "TXN-123"; }
}
Ну и как, спрашивается, эту манду с ушами впихнуть в нашу аккуратную систему? Правильно, через адаптер! Делаем прослойку.
// 3. Сам адаптер. Надеваем на чужой класс маску нашего интерфейса.
class WeirdPaymentAdapter implements IPaymentProcessor {
private WeirdPaymentGateway gateway; // Прячем внутри эту странную хуйню
private String lastAuthCode;
public WeirdPaymentAdapter(WeirdPaymentGateway gateway) {
this.gateway = gateway;
}
@Override
public void authorize(double amount) {
// А тут магия: наш метод -> вызов ихнего метода с нужными параметрами.
gateway.authPayment(amount, "USD");
lastAuthCode = "AUTH_CODE_XYZ";
}
@Override
public void capture(String transactionId) {
// И тут тоже: подменяем логику.
String result = gateway.completeAuth(lastAuthCode);
System.out.println("Платёж проведён через адаптер. Транзакция: " + result);
}
}
И теперь главный фокус. Весь остальной твой код, весь этот овердохуища бизнес-логики, работает как ни в чём не бывало.
// 4. Клиенту (основному коду) похуй, что там внутри. Он видит знакомый интерфейс.
public class Main {
public static void main(String[] args) {
// Просто создаём адаптер, засунув в него странный гейтвей.
IPaymentProcessor processor = new WeirdPaymentAdapter(new WeirdPaymentGateway());
processor.authorize(100.0); // Вызываем наши методы...
processor.capture("some-id"); // ...а адаптер внутри сам всё переводит на язык дикарей.
}
}
Итог, чувак: Адаптер — это не волшебная таблетка, которая добавляет новый функционал. Это такой технический переводчик-приспособленец, который берёт один интерфейс и натягивает на него шкуру другого, чтобы всем было удобно. Без него пришлось бы переписывать либо свою систему, либо уговаривать тех пидарасов шерстяных поменять их код. А так — чих-пых тебя в сраку — и всё работает.