Библиотека 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
🏗 Порождающие паттерны: Как рождаются объекты?

Создать объект просто: User u = new User().
А если у объекта 20 полей? А если нам нужен только один экземпляр на всё приложение? А если мы не знаем заранее, какой именно класс нам нужен?
Тут на сцену выходят паттерны.

1️⃣ Singleton (Одиночка)

Суть: Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.

Где нужен: Логгеры, Конфигурация, Пул соединений с БД.

Как реализовать:

1. Скрываем конструктор (private).
2. Создаем статическое поле с экземпляром.
3. Возвращаем его через статический метод.


public class Database {
// Единственный экземпляр
private static Database instance;

private Database() {} // Никто не создаст объект извне

public static synchronized Database getInstance() {
if (instance == null) {
instance = new Database();
}
return instance;
}
}



⚠️ Важно: В Spring Boot все бины по умолчанию - синглтоны. Вам не нужно писать этот код руками, контейнер Spring сам следит, чтобы сервис был создан один раз.


2️⃣ Builder (Строитель)

Суть: Позволяет создавать сложные объекты пошагово. Спасает от «Телескопического конструктора» (когда у вас конструктор с 10 аргументами, и вы не помните, где там age, а где height).

Было (Ужас):
new User("Alex", null, true, "admin", 25, null);

Стало (Builder):


User user = User.builder()
.name("Alex")
.age(25)
.role("ADMIN")
.active(true)
.build();



🛠 Лайфхак:
В Java не нужно писать Билдер руками (это 50 строк кода). Просто поставьте аннотацию Lombok @Builder над классом.


3️⃣ Factory Method (Фабричный метод)

Суть: Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанцировать.
Это реализация принципа Open-Closed. Мы добавляем новые типы продуктов, не ломая существующий код.

Пример: У нас есть "Уведомления". Сегодня это Email, завтра SMS, послезавтра Push.


// 1. Интерфейс
interface Notification { void send(String msg); }

// 2. Реализации
class EmailNotification implements Notification { ... }
class SmsNotification implements Notification { ... }

// 3. Фабрика (Решает, что создать)
class NotificationFactory {
public static Notification create(String type) {
return switch (type) {
case "EMAIL" -> new EmailNotification();
case "SMS" -> new SmsNotification();
default -> throw new IllegalArgumentException("Unknown type");
};
}
}

// Клиентский код (не знает про классы Email/Sms, знает только интерфейс)
Notification notification = NotificationFactory.create("SMS");
notification.send("Hello!");



🔥 Итог

1. Singleton - когда нужен один объект на всю систему.
2. Builder - когда объект сложный и у него много параметров.
3. Factory - когда мы не знаем заранее, какой конкретно объект понадобится, или хотим скрыть логику выбора.

#DesignPatterns #GoF #Singleton #Builder #Factory #Java

📲 Мы в MAX

👉@BookJava
👍5🔥3
🧅 Архитектура: От Слоев к Луковице

Проблема Слоенки (Database Driven Design)

В классическом Spring-приложении зависимости идут сверху вниз:

1. Контроллер зависит от Сервиса.
2. Сервис зависит от Репозитория (Базы данных).

В чем подвох?
Ваша бизнес-логика (Сервис) намертво привязана к деталям хранения данных (БД).

🔴Хотите поменять SQL на NoSQL? Переписывайте сервис.

🔴Хотите протестировать логику? Придется мокать базу данных.

🔴Главный грех: База данных диктует, как писать бизнес-логику. А должно быть наоборот!


Решение: Clean / Hexagonal / Onion

Дядя Боб, Алистер Кокберн и другие умные дядьки придумали, как перевернуть игру.
Главная идея: Зависимости должны быть направлены ТОЛЬКО внутрь, к центру.

Представьте приложение как Луковицу.

1. Ядро (Core / Domain) - Центр Вселенной

Здесь живет ваша Бизнес-логика.

🔴Сущности (User, Order).

🔴Правила (User не может быть моложе 18 лет).

🔴Правило: Здесь НЕТ фреймворков. Никакого Spring, никакого Hibernate, никакого SQL. Только чистая Java.

🔴Этот слой ничего не знает о внешнем мире.

2. Порты (Ports / Use Cases) - Граница

Ядро определяет интерфейсы (Порты), которые ему нужны для работы.

🔴Например: interface UserRepository (найти пользователя, сохранить пользователя).

🔴Заметьте: интерфейс лежит внутри домена!

3. Адаптеры (Adapters / Infrastructure) - Внешний мир

Здесь живут детали реализации.

🔴PostgresUserRepository реализует интерфейс UserRepository.

🔴RestController вызывает методы Ядра.

🔴Здесь подключается Spring, Hibernate, Kafka и всё остальное.

🔄 Инверсия Зависимостей (DIP)

Следите за руками:

1. В слоеной архитектуре: Service зависит от PostgresDao.
2. В чистой архитектуре: Service зависит от Интерфейса. А PostgresDao зависит от Интерфейса.

Оба зависят от абстракции. БД стала просто плагином. Вы можете выкинуть Postgres и поставить заглушку (In-Memory Map) - и бизнес-логика даже не заметит подмены!

⚖️ Когда что использовать?

1. Layered (Controller-Service-Repo)

Простые CRUD-приложения.
Админки, прототипы.
Когда логики почти нет, просто перекладываем данные.

2. Hexagonal (Ports & Adapters)

Сложная бизнес-логика (Банкинг, Финтех, Логистика).
Приложение живет долго (5+ лет).
Нужно писать много Unit-тестов для ядра, не поднимая контекст Spring.

🔥 Итог

🔴Layered: Быстро писать, сложно поддерживать. БД - главная.
🔴Clean: Дольше писать (много маппингов DTO <-> Entity), легко поддерживать. Логика - главная.

#Architecture #CleanArchitecture #Hexagonal #Spring #Java

📲 Мы в MAX

👉@BookJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥2