Что такое структурные паттерны проектирования? Приведи пример паттерна Адаптер.

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

Ответ

Структурные паттерны — это паттерны проектирования, которые описывают способы компоновки объектов и классов в более крупные, гибкие и эффективные структуры, сохраняя при этом их расширяемость.

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

Аналогия: Переходник с USB-C на USB-A позволяет новому ноутбуку работать со старой флешкой.

Пример реализации в Java:

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

// 2. Адаптируемый класс со своим специфическим интерфейсом (старая флешка с USB-A)
class LegacyUsbPort {
    public void plugIn() {
        System.out.println("Legacy USB device connected.");
    }
}

// 3. Адаптер. Реализует целевой интерфейс и содержит ссылку на адаптируемый объект.
class UsbAdapter implements UsbConnector {
    private LegacyUsbPort legacyPort;

    public UsbAdapter(LegacyUsbPort legacyPort) {
        this.legacyPort = legacyPort;
    }

    @Override
    public void connectUsb() {
        // Адаптер «переводит» вызов connectUsb() в вызов plugIn()
        legacyPort.plugIn();
    }
}

// 4. Клиентский код, который работает только с целевым интерфейсом
public class ModernLaptop {
    public void useDevice(UsbConnector connector) {
        connector.connectUsb();
    }

    public static void main(String[] args) {
        ModernLaptop laptop = new ModernLaptop();
        LegacyUsbPort oldFlashDrive = new LegacyUsbPort();

        // Используем адаптер для подключения старого устройства
        UsbConnector adapter = new UsbAdapter(oldFlashDrive);
        laptop.useDevice(adapter); // Вывод: "Legacy USB device connected."
    }
}

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

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