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

Ответ

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");
    }
}

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

Ответ 18+ 🔞

Слушай, я тут на днях вникал в этот ваш паттерн «Адаптер». Ну, ёпта, классика жанра, как старый добрый переходник для розетки. Представь: купил ты на алиэкспрессе крутую китайскую гирлянду, а вилка у неё — какая-то пизда с ушами, три квадратных штыря. И ты стоишь с этой хуйней перед нашей родной розеткой, и волнение ебать — как это всё соединить? Вот адаптер — он и есть эта самая переходная хуйня, которая позволяет твоей новой гирлянде засветиться в старой системе.

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

Когда это нужно, спросишь? Да элементарно:

  1. Подключаешь какую-то стороннюю библиотеку или сервис, который написан каким-то пидарасом шерстяным, у которого свои понятия о красоте API.
  2. Работаешь с легаси-кодом, древним и страшным, который трогать страшно, но использовать надо. Типа дедушкиного мотоцикла, который заводится с пинка, но жрёт бензина дохуя.
  3. Хочешь привести к общему знаменателю кучу разных классов, которые делают одно и то же, но называют это разными словами.

Смотри, вот живой пример, чтобы совсем понятно стало. Допустим, вся твоя система заточена под красивый, стандартный интерфейс для платежей.

// 1. Это наш родной, понятный интерфейс (Цель). Его ждёт вся система.
interface IPaymentProcessor {
    void authorize(double amount);
    void capture(String transactionId);
}

А тут ты решил подключить новую платёжку «Рога и копыта». А её разработчики, видимо, с луны свалились, потому что их API — это просто ядрёна вошь.

// 2. Сторонний класс с ебанутым интерфейсом (Адаптируемый).
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("Платёж проведён через адаптер. Транзакция: " + result);
    }
}

И теперь главный фокус. Весь остальной твой код, весь этот овердохуища бизнес-логики, работает как ни в чём не бывало.

// 4. Клиенту (основному коду) похуй, что там внутри. Он видит знакомый интерфейс.
public class Main {
    public static void main(String[] args) {
        // Просто создаём адаптер, засунув в него странный гейтвей.
        IPaymentProcessor processor = new WeirdPaymentAdapter(new WeirdPaymentGateway());
        processor.authorize(100.0); // Вызываем наши методы...
        processor.capture("some-id"); // ...а адаптер внутри сам всё переводит на язык дикарей.
    }
}

Итог, чувак: Адаптер — это не волшебная таблетка, которая добавляет новый функционал. Это такой технический переводчик-приспособленец, который берёт один интерфейс и натягивает на него шкуру другого, чтобы всем было удобно. Без него пришлось бы переписывать либо свою систему, либо уговаривать тех пидарасов шерстяных поменять их код. А так — чих-пых тебя в сраку — и всё работает.