← Назад к вопросам

Для чего нужен шаблон Adapter?

1.8 Middle🔥 201 комментариев
#SOLID и паттерны проектирования#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Паттерн Adapter в Java

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

Основное назначение

Адаптер используется когда:

  • Нужно использовать существующий класс, но его интерфейс несовместим с остальным кодом
  • Нужно интегрировать библиотеку со старым интерфейсом в новый код
  • Нужно работать с несколькими вариантами интерфейса

Реальный пример: адаптер для зарядки телефона

Телефон ожидает USB-C, но у вас есть только адаптер Micro-USB. Адаптер преобразует Micro-USB в USB-C.

Классический пример: Adapter с наследованием

// Старый интерфейс (невозможно изменить)
interface OldPaymentSystem {
    void payByCash(double amount);
    void payByCheck(double amount);
}

// Новый интерфейс, который ожидает приложение
interface NewPaymentGateway {
    void processPayment(double amount, String method);
}

// Реализация старого интерфейса
class LegacyBank implements OldPaymentSystem {
    @Override
    public void payByCash(double amount) {
        System.out.println("Оплата наличными: " + amount);
    }
    
    @Override
    public void payByCheck(double amount) {
        System.out.println("Оплата чеком: " + amount);
    }
}

// Адаптер — преобразует OldPaymentSystem в NewPaymentGateway
public class PaymentAdapter implements NewPaymentGateway {
    private OldPaymentSystem oldSystem;
    
    public PaymentAdapter(OldPaymentSystem oldSystem) {
        this.oldSystem = oldSystem;
    }
    
    @Override
    public void processPayment(double amount, String method) {
        if ("cash".equalsIgnoreCase(method)) {
            oldSystem.payByCash(amount);
        } else if ("check".equalsIgnoreCase(method)) {
            oldSystem.payByCheck(amount);
        }
    }
}

// Использование
class Shop {
    private NewPaymentGateway paymentGateway;
    
    public Shop(NewPaymentGateway gateway) {
        this.paymentGateway = gateway;
    }
    
    public void checkout(double amount) {
        paymentGateway.processPayment(amount, "cash");
    }
}

public class Main {
    public static void main(String[] args) {
        OldPaymentSystem oldBank = new LegacyBank();
        NewPaymentGateway adapter = new PaymentAdapter(oldBank);
        Shop shop = new Shop(adapter);
        shop.checkout(100.0);
        // Вывод: Оплата наличными: 100.0
    }
}

Примеры адаптеров в Java

1. Collections.list() — адаптер Enumeration в List:

// Старый интерфейс (до Java 1.2)
Enumeration<String> oldEnum = new StringTokenizer("apple,banana,cherry", ",");

// Новый интерфейс
List<String> fruits = Collections.list(oldEnum);
for (String fruit : fruits) {
    System.out.println(fruit);
}

2. Arrays.asList() — адаптер массива в List:

String[] arr = {"a", "b", "c"};
List<String> list = Arrays.asList(arr); // Адаптирует массив к List
for (String s : list) {
    System.out.println(s);
}

3. InputStreamReader — адаптер InputStream в Reader:

// InputStream — работает с байтами
InputStream is = new FileInputStream("file.txt");

// Адаптируем в Reader (работает с символами)
Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8);

Adapter через наследование (Class Adapter)

class LegacySystem {
    public void oldMethod() {
        System.out.println("Старый метод");
    }
}

// Адаптер наследует старый класс и реализует новый интерфейс
class ClassAdapter extends LegacySystem implements NewInterface {
    @Override
    public void newMethod() {
        oldMethod(); // Переиспользуем старый метод
    }
}

interface NewInterface {
    void newMethod();
}

Разница: Adapter vs Bridge vs Facade

  • Adapter: Преобразует несовместимые интерфейсы
  • Bridge: Разделяет абстракцию от реализации (для независимого развития)
  • Facade: Предоставляет упрощённый интерфейс к сложной системе

Преимущества и недостатки

Преимущества:

  • Позволяет использовать несовместимые классы вместе
  • Не требует изменения исходного кода
  • Разделение ответственности

Недостатки:

  • Добавляет новый класс в иерархию
  • Может усложнить код при большом количестве адаптеров
  • Производительность (если много вызовов через адаптер)