Структурные (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.
• как Spring использует Proxy под капотом для `@Transactional`/`@Cacheable` (если дошёл до 2-го слоя).