Что такое паттерн проектирования Адаптер (Adapter)?

«Что такое паттерн проектирования Адаптер (Adapter)?» — вопрос из категории Паттерны, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Паттерн Адаптер (Adapter) — это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе. Он выступает в роли "переводчика" или "прослойки", преобразуя интерфейс одного класса в интерфейс, ожидаемый клиентом.

Аналогия: Электрический адаптер, позволяющий вилке одного стандарта работать в розетке другого.

Участники:

  1. Целевой интерфейс (Target): Интерфейс, который ожидает клиент.
  2. Адаптируемый класс (Adaptee): Существующий класс с несовместимым интерфейсом.
  3. Адаптер (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...

Когда использовать:

  • Интеграция старого легаси-кода или сторонних библиотек.
  • Необходимость использовать несколько классов с разными интерфейсами единообразно.
  • Вы хотите изолировать основной код от деталей конкретных реализаций.

Отличие от Декоратора: Адаптер меняет интерфейс объекта, а Декоратор расширяет его функциональность, не меняя интерфейса.