Библиотека Java разработчика
10.5K subscribers
1.17K photos
594 videos
58 files
1.51K links
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate.


По всем вопросам @evgenycarter

РКН clck.ru/3KoGeP
Download Telegram
🏗 Структурные паттерны: Адаптер, Декоратор, Прокси

Когда вы пытаетесь соединить старую библиотеку с новым кодом или добавить логирование, не переписывая половину проекта - вы используете эти паттерны.

🔌 1. Adapter (Адаптер)

Суть: Делает несовместимые интерфейсы совместимыми.
Это как переходник для розетки. У вас вилка американская, а розетка европейская. Адаптер позволяет им работать вместе.

Где нужен: Когда есть старый класс (Legacy), который нельзя менять, но его нужно использовать в новом коде.

Пример: У нас есть система, которая понимает только KM/H (километры), а внешняя библиотека выдает скорость в MPH (мили).


// 1. Наш интерфейс (чего мы ждем)
interface Movable { double getSpeed(); } // км/ч

// 2. Чужой класс (что есть)
class Bugatti {
double getSpeedMph() { return 268; }
}

// 3. Адаптер (Переводчик)
class MovableAdapter implements Movable {
private Bugatti bugatti;

public MovableAdapter(Bugatti bugatti) {
this.bugatti = bugatti;
}

@Override
public double getSpeed() {
return convertMphToKmph(bugatti.getSpeedMph());
}
}




🎁 2. Decorator (Декоратор/Обертка)

Суть: Динамически добавляет объекту новые обязанности (функционал).
Это альтернатива наследованию. Вместо того чтобы создавать CoffeeWithMilkAndSugar, мы берем Coffee и заворачиваем его в Milk, а потом в Sugar.

Принцип: Матрешка. Каждый декоратор делает свою работу и вызывает следующий.

Пример:


// Базовый кофе
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getCost()); // 10$

// Добавили молоко (Обернули)
coffee = new MilkDecorator(coffee);
System.out.println(coffee.getCost()); // 12$

// Добавили сахар (Обернули еще раз)
coffee = new SugarDecorator(coffee);
System.out.println(coffee.getCost()); // 13$



Важно: В java.io это используется повсюду: new BufferedReader(new FileReader(file)).


🛡️ 3. Proxy (Заместитель)

Суть: Объект-прокладка, который контролирует доступ к другому объекту.
Клиент думает, что общается с реальным объектом, а на самом деле говорит с его заместителем.

Зачем?

1. Ленивая загрузка (Lazy Loading): Не грузить тяжелую картинку/БД, пока ее реально не попросят.

2. Безопасность: Проверить права доступа перед выполнением метода.

3. Логирование: Записать "Метод вызван" и передать вызов дальше.

Пример:


interface Image { void display(); }

class RealImage implements Image {
public RealImage(String file) { loadFromDisk(file); } // Долгая операция!
public void display() { System.out.println("Displaying..."); }
}

class ProxyImage implements Image {
private RealImage realImage;
private String file;

public ProxyImage(String file) { this.file = file; }

@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(file); // Грузим только сейчас!
}
realImage.display();
}
}



Spring Magic: Весь Spring держится на Прокси! Когда вы ставите @Transactional, Spring создает прокси вокруг вашего сервиса, открывает транзакцию, вызывает ваш метод, а потом закрывает транзакцию.


🔥 Итог

🔴Adapter - меняет интерфейс объекта (чтобы подошел).

🔴Decorator - меняет поведение объекта (добавляет фичи), не меняя интерфейс.

🔴Proxy - контролирует доступ к объекту (ленивость, защита).

#DesignPatterns #Adapter #Decorator #Proxy #Architecture

📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7