Карта / Паттерны проектирования / Структурные (Adapter, Proxy)

Структурные (Adapter, Proxy)

Структурные паттерны решают вопрос «как соединить объекты друг с другом», не делая систему хрупкой. Два самых частых — Adapter и Proxy.

Adapter — превращает один интерфейс в другой, который ожидает твой код. Используется, когда подключаешь стороннюю библиотеку с неудобным/несовместимым API:

interface ModernPayment { void pay(int amountInCents); }

class OldPaymentSystem {                            // старая библиотека, менять нельзя
    void makePayment(double amountInDollars) { ... }
}

class PaymentAdapter implements ModernPayment {       // адаптер "переводит" вызов
    private final OldPaymentSystem old = new OldPaymentSystem();
    public void pay(int amountInCents) {
        old.makePayment(amountInCents / 100.0);
    }
}

Proxy — объект-заместитель, который стоит перед реальным объектом и добавляет своё поведение (проверку прав, кэш, логирование) до или после вызова настоящего метода:

interface Service { String getData(); }

class RealService implements Service {
    public String getData() { return "тяжёлые данные из БД"; }
}

class CachingProxy implements Service {
    private final RealService real = new RealService();
    private String cached;
    public String getData() {
        if (cached == null) cached = real.getData();   // первый раз — реальный вызов
        return cached;                                    // дальше — из кэша
    }
}
Копнуть глубже

Adapter не меняет поведение, только “переводит” интерфейс — он не добавляет логики, только подгоняет несовместимые формы под общий контракт.

Proxy добавляет поведение, сохраняя тот же интерфейс — вызывающий код вообще не знает, что вызывает не реальный объект, а обёртку.

Spring построен на прокси. @Transactional, @Cacheable, AOP-аспекты (см. тему «Как работают прокси») — всё это реализовано через автоматически создаваемые прокси-объекты вокруг твоих бинов. Когда вызываешь метод с @Transactional, на самом деле вызывается метод прокси, который открывает транзакцию, потом вызывает твой реальный метод, потом коммитит/откатывает — ты этот код не видишь, но это и есть паттерн Proxy в действии повсюду в Spring.

🎤 Закрыл тему, если можешь объяснить:
• разницу между Adapter (переводит интерфейс) и Proxy (добавляет поведение);
• как Spring использует Proxy под капотом для `@Transactional`/`@Cacheable` (если дошёл до 2-го слоя).