Ответ
Паттерн Адаптер (Adapter) — это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе. Он выступает в роли "переводчика" или "прослойки", преобразуя интерфейс одного класса в интерфейс, ожидаемый клиентом.
Аналогия: Электрический адаптер, позволяющий вилке одного стандарта работать в розетке другого.
Участники:
- Целевой интерфейс (Target): Интерфейс, который ожидает клиент.
- Адаптируемый класс (Adaptee): Существующий класс с несовместимым интерфейсом.
- Адаптер (Adapter): Класс, который реализует целевой интерфейс и оборачивает экземпляр адаптируемого класса, переводя вызовы.
Реализация (объектный адаптер, использует композицию):
// 1. Целевой интерфейс, ожидаемый клиентским кодом (новый стандарт)
interface USB_C {
void connectWithUsbC();
}
// 2. Адаптируемый класс со старым интерфейсом
class MicroUSBCharger {
public void plugInMicroUSB() {
System.out.println("Charging via MicroUSB...");
}
}
// 3. Адаптер
class MicroUSBToUSBCAdapter implements USB_C {
private MicroUSBCharger microUSBCharger; // Композиция
public MicroUSBToUSBCAdapter(MicroUSBCharger charger) {
this.microUSBCharger = charger;
}
@Override
public void connectWithUsbC() {
// Адаптер преобразует вызов нового метода в старый
System.out.print("Adapter is converting USB-C to MicroUSB. ");
microUSBCharger.plugInMicroUSB();
}
}
// 4. Клиентский код
public class Client {
public static void main(String[] args) {
USB_C modernPort = new MicroUSBToUSBCAdapter(new MicroUSBCharger());
modernPort.connectWithUsbC(); // Работает со старым зарядным устройством!
}
}
// Вывод: Adapter is converting USB-C to MicroUSB. Charging via MicroUSB...
Когда использовать:
- Интеграция старого легаси-кода или сторонних библиотек.
- Необходимость использовать несколько классов с разными интерфейсами единообразно.
- Вы хотите изолировать основной код от деталей конкретных реализаций.
Отличие от Декоратора: Адаптер меняет интерфейс объекта, а Декоратор расширяет его функциональность, не меняя интерфейса.
Ответ 18+ 🔞
Давай я тебе на пальцах объясню, что за зверь такой — этот Адаптер. Представь, у тебя есть новый, охуенный телефон с разъёмом USB-C, а зарядка — старая, с этим дурацким MicroUSB. И ты такой: «Ну ёпта, как теперь заряжать?». А потом находишь в ящике эту маленькую хуйню — переходничок. Вот это и есть адаптер, блядь! Он берёт один интерфейс (твой новый порт) и превращает его в другой (старый разъём), чтобы всё заработало. Гениально и просто, как тапок.
Кто тут кто, разберём по косточкам:
- Целевой интерфейс (Target): Это то, чего ты хочешь. Твой новый телефон орет: «Давай сюда USB-C, иначе нихуя не будет!».
- Адаптируемый класс (Adaptee): Это твоя старая зарядка, упоротая, которая мычит: «Я умею только в MicroUSB пихаться, иди нахуй».
- Адаптер (Adapter): Сам переходник, хитрая жопа. С одной стороны он делает вид, что он USB-C (целевой интерфейс), а с другой — внутри у него торчит эта старая зарядка, и он шепчет ей: «Спокойно, я всё уладю».
Смотри, как это в коде выглядит, тут всё честно:
// 1. Это твой новый, строгий порядок. Хочу USB-C и всё тут!
interface USB_C {
void connectWithUsbC();
}
// 2. А это дед, который в пещере жил. Умеет только одно.
class MicroUSBCharger {
public void plugInMicroUSB() {
System.out.println("Charging via MicroUSB...");
}
}
// 3. А вот и наш спаситель, переводчик с буржуйского на деревенский!
class MicroUSBToUSBCAdapter implements USB_C {
private MicroUSBCharger microUSBCharger; // Прячет старика внутри
public MicroUSBToUSBCAdapter(MicroUSBCharger charger) {
this.microUSBCharger = charger;
}
@Override
public void connectWithUsbC() {
// Магия происходит здесь! Говорит на новом языке, а делает по-старому.
System.out.print("Adapter is converting USB-C to MicroUSB. ");
microUSBCharger.plugInMicroUSB(); // А тут старикан своё дело делает
}
}
// 4. Ты, довольный пользователь
public class Client {
public static void main(String[] args) {
// Берёшь старую зарядку, суёшь в адаптер — и вуаля, она теперь как новая!
USB_C modernPort = new MicroUSBToUSBCAdapter(new MicroUSBCharger());
modernPort.connectWithUsbC(); // И работает, ёба!
}
}
// На экране: Adapter is converting USB-C to MicroUSB. Charging via MicroUSB...
Когда эту штуку впиндюривать в проект?
- Когда подключаешь какую-нибудь старую библиотеку, написанную ещё при царе Горохе, а переписывать её — терпения ноль ебать.
- Когда нужно, чтобы десять классов, которые говорят на разных языках (один мычит, другой блеет), делали вид, что они одинаковые.
- Когда хочешь отгородить свою чистенькую логику от этого легаси-говна, чтобы оно в одном адаптере сидело и не высовывалось.
Важный момент, чтобы не спутать с другим паттерном:
Адаптер — это обманщик. Он меняет лицо (интерфейс) объекта, чтобы ты думал, что это что-то другое. А вот, например, Декоратор — это улучшатель. Он не меняет лицо, он просто надевает на объект новые шмотки (добавляет функциональность), а интерфейс остаётся тем же. Не перепутай, а то будет пиздец.