Для чего нужен паттерн Adapter?

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

Ответ

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

Типичные ситуации для применения:

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

Пример: Интеграция платёжной системы со странным 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");
    }
}

Итог: Адаптер не добавляет новой функциональности, он только преобразует один интерфейс в другой, обеспечивая совместимость.