В чём суть шаблона проектирования Adapter (Адаптер)?

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

Ответ

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

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

Реализация в Java:

// 1. Целевой интерфейс, который ожидает клиент (например, розетка USB-C)
interface UsbCCharger {
    void chargeWithUsbC();
}

// 2. Адаптируемый класс со старым интерфейсом (например, зарядка MicroUSB)
class MicroUsbCharger {
    public void chargeWithMicroUsb() {
        System.out.println("Charging with MicroUSB...");
    }
}

// 3. Адаптер, реализующий целевой интерфейс и содержащий ссылку на адаптируемый объект
class MicroUsbToUsbCAdapter implements UsbCCharger {
    private MicroUsbCharger microUsbCharger;

    public MicroUsbToUsbCAdapter(MicroUsbCharger microUsbCharger) {
        this.microUsbCharger = microUsbCharger;
    }

    @Override
    public void chargeWithUsbC() {
        // Адаптер преобразует вызов нового метода в вызов старого
        microUsbCharger.chargeWithMicroUsb();
        System.out.println("  (via Adapter)");
    }
}

// 4. Клиентский код, который работает только с целевым интерфейсом
public class Client {
    public static void main(String[] args) {
        MicroUsbCharger oldCharger = new MicroUsbCharger();
        // Используем адаптер для подключения старой зарядки к новому устройству
        UsbCCharger adapter = new MicroUsbToUsbCAdapter(oldCharger);
        adapter.chargeWithUsbC(); // Вывод: Charging with MicroUSB... (via Adapter)
    }
}

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

  • Интеграция старого (legacy) кода в новую систему.
  • Использование сторонних библиотек с неподходящим интерфейсом.
  • Создание универсального интерфейса для работы с несколькими классами, имеющими разную функциональность.

Плюсы:

  • Отделяет и скрывает код преобразования интерфейсов от бизнес-логики.
  • Повышает переиспользуемость кода.

Минусы:

  • Усложняет систему за счет введения дополнительных классов.