Библиотека собеса по Java | вопросы с собеседований
6.48K subscribers
410 photos
9 videos
626 links
Вопросы с собеседований по Java и ответы на них.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/08c603b6

Для обратной связи: @proglibrary_feeedback_bot
Download Telegram
Расскажите о паттерне Flyweight

Flyweight — это структурный паттерн, который позволяет вместить большее количество объектов в отведённую оперативную память за счёт разделения общего состояния между объектами.

Простыми словами: вместо создания тысяч похожих объектов, вы создаёте несколько объектов-легковесов с общими данными и передаёте уникальные данные извне при использовании.

▪️ Пример

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

// Flyweight — легковес с общим состоянием
class CharacterStyle {
private final String font; // внутреннее состояние
private final int size; // (intrinsic)
private final String color;
public CharacterStyle(String font, int size, String color) {
this.font = font;
this.size = size;
this.color = color;
}

public void render(char character, int x, int y) { // внешнее состояние
System.out.println("Рендер '" + character +
"' в позиции (" + x + "," + y + ")");
}
}
// Фабрика для переиспользования flyweight-объектов
class StyleFactory {
private Map<String, CharacterStyle> styles = new HashMap<>();
public CharacterStyle getStyle(String font, int size, String color) {
String key = font + size + color;
return styles.computeIfAbsent(key,
k -> new CharacterStyle(font, size, color));
}
}
// Использование
StyleFactory factory = new StyleFactory();
// Миллион символов используют всего несколько объектов стилей
CharacterStyle arial12 = factory.getStyle("Arial", 12, "black");
arial12.render('H', 0, 0);
arial12.render('e', 10, 0);
arial12.render('l', 20, 0);
arial12.render('l', 30, 0);
arial12.render('o', 40, 0);


▪️ Когда использовать


Приложение создаёт огромное количество однотипных объектов
Объекты потребляют много памяти
Большую часть состояния можно вынести за пределы объекта
Приложение не зависит от идентичности объектов (можно переиспользовать)

▪️ Минусы

Усложнение кода из-за разделения состояния
Flyweight должен быть immutable для безопасного переиспользования

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71🔥1
Как выбрать между монолитом, модульным монолитом и микросервисами при проектировании системы?

Выбор зависит от нескольких факторов: размера команды, требований к масштабированию и сложности бизнес-логики.

🔹 Монолит подходит для MVP, стартапов и небольших команд. Все в одном приложении — проще разрабатывать, тестировать и деплоить. Минус — со временем становится сложно поддерживать из-за связанности компонентов.

🔹 Модульный монолит — это компромисс. Архитектура разбита на модули с четкими границами, но все еще в одном деплойменте. Отличный вариант, когда нужна структура микросервисов без их операционной сложности. Позволяет в будущем безболезненно выделить модули в отдельные сервисы.

🔹Микросервисы выбираем, когда есть реальная необходимость: разные части системы масштабируются по-разному, работают большие независимые команды, нужна изоляция отказов. Но это дорого — требуется инфраструктура для мониторинга, трейсинга, service discovery, обработки распределенных транзакций.

#patterns

🐸 Библиотека собеса по Java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥1🥰1👏1
Что такое Dependency Injection?

Dependency Injection (внедрение зависимостей) — это один из основных паттернов проектирования в программировании, который позволяет объектам получать свои зависимости извне, вместо того чтобы создавать их внутри себя.

DI способствует:

Слабой связанности между компонентами.
Легкости тестирования за счет использования mock-объектов.
Повторному использованию кода.

Основные способы внедрения зависимостей в Spring:

🔹 Constructor Injection

Зависимости передаются через конструктор.
public class Service {
private final Repository repository;

public Service(Repository repository) {
this.repository = repository;
}
}


🔹Setter Injection

Зависимости передаются через сеттеры.
public class Service {
private Repository repository;

public void setRepository(Repository repository) {
this.repository = repository;
}
}


🔹 Field Injection

Зависимости внедряются напрямую в поля класса (обычно с помощью фреймворков, например Spring).
@Component
public class Service {
@Autowired
private Repository repository;
}


🐸 Библиотека собеса по Java

#patterns #лучшее2025
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥42👏1
Что такое микросервисы?

Микросервисы — это архитектурный стиль, при котором приложение разбивается на небольшие, независимые сервисы. Каждый сервис отвечает за определённую бизнес-логику, имеет собственную базу данных (или логически обособленное хранилище) и взаимодействует с другими сервисами через API (обычно REST или gRPC).

🔹 Ключевые принципы

Можно обновлять и масштабировать отдельные сервисы без затрагивания всей системы.
Каждый сервис выполняет свою узкую задачу.
У сервиса свои изолированные данные, код и зависимости.
Сервисы общаются через HTTP, AMQP, Kafka и другие механизмы.

🐸 Библиотека собеса по Java

#patterns #лучшее2025
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥2👏1🤔1
Что такое паттерн Flyweight и где он используется в Java?

Flyweight — это паттерн для экономии памяти путём переиспользования объектов с одинаковым состоянием.

Объект разделяется на intrinsic state (неизменяемое, общее) и extrinsic state (изменяемое, уникальное). Общее состояние хранится в одном экземпляре.

🔹 Примеры:

String Pool (все одинаковые строки ссылаются на один объект)
Integer.valueOf() кеширует числа от -128 до 127
Boolean.TRUE и Boolean.FALSE

Паттерн эффективен, когда создаётся много объектов с повторяющимися данными.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥1🤔1
Расскажите о паттерне Singleton и где он используется?

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

public class DatabaseConnection {
private static volatile DatabaseConnection instance;

private DatabaseConnection() {}

public static DatabaseConnection getInstance() {
if (instance == null) {
synchronized (DatabaseConnection.class) {
if (instance == null) {
instance = new DatabaseConnection();
}
}
}
return instance;
}
}


Реальные кейсы

Пул соединений с БД (HikariCP держит один менеджер пула)
Логгер (LoggerFactory в SLF4J)
Конфигурация приложения (Spring ApplicationContext — де-факто синглтон)
Кэш в памяти

Подводные камни: проблемы с многопоточностью (решается через volatile + double-checked locking или enum), сложность тестирования, скрытые зависимости.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍92🔥1
Что такое Transactional Outbox?

Это паттерн надёжной доставки событий в распределённых системах.

Проблема: при сохранении данных в БД и отправке события в Kafka/RabbitMQ — эти две операции не атомарны. Возможны ситуации, когда данные сохранятся, но событие не уйдёт, либо наоборот.

Решение: вместо прямой отправки в брокер — пишем событие в отдельную таблицу outbox в рамках одной транзакции с основными данными. Отдельный процесс читает эту таблицу и публикует события в брокер.

🔹 Ключевые свойства

Гарантия at-least-once доставки.
Атомарность через одну транзакцию БД.
Потребитель должен быть идемпотентен.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍103🔥1
Что такое MVC?

MVC (Model-View-Controller) — это архитектурный шаблон, разделяющий приложение на три компонента:

▪️ Model (Модель) — содержит бизнес-логику
▪️ View (Представление) — отображает данные пользователю, получая их от модели
▪️ Controller (Контроллер) — обрабатывает входные данные (обычно от пользователя), вызывает нужные методы модели и обновляет представление

Этот подход упрощает сопровождение кода, позволяет разделить ответственность между слоями и облегчает тестирование.

🐸Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71😁1
Что такое DDD?

DDD (Domain-Driven Design) — подход к проектированию, при котором структура кода отражает структуру бизнес-домена.

Основные строительные блоки

Entity — объект с уникальной идентичностью. Два объекта с одним ID — один и тот же объект, даже если остальные поля разные. Пример: User, Order.

Value Object — объект без идентичности, определяется своими атрибутами. Иммутабелен. Пример: Money(100, 'USD'), Email('alice@example.com'). Два Money(100, 'USD') — одно и то же значение.

Aggregate — кластер связанных сущностей с одним корнем (Aggregate Root). Все изменения внутри агрегата — только через корень. Граница транзакции = граница агрегата. Пример: Order содержит OrderItems, но только Order — корень.

Domain Service — бизнес-операция, которая не принадлежит ни одной сущности. Пример: TransferService(fromAccount, toAccount, amount).

Repository — абстракция доступа к хранилищу для агрегатов. Один репозиторий — один агрегат.

Domain Event — факт, произошедший в домене. OrderPlaced, PaymentFailed.

Bounded Context — явная граница, внутри которой модель имеет единое значение. User в контексте Billing ≠ User в контексте Shipping.

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍63🔥1
Сохраняешь Order в БД и отправляешь событие в Kafka. Как гарантировать, что событие не потеряется и не задвоится?

Outbox Pattern

Сохраняй событие в таблицу outbox в той же транзакции, что и бизнес-данные. Отдельный процесс читает таблицу и публикует в Kafka.

На стороне консьюмера — идемпотентность: проверяй event_id перед обработкой.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61🔥1
Расскажите о паттерне Strategy?

Strategy — это поведенческий паттерн, который позволяет определить семейство алгоритмов, инкапсулировать каждый из них и сделать их взаимозаменяемыми.

Когда использовать:

есть несколько способов выполнения одной операции;
нужно избежать множественных if-else или switch;
алгоритмы должны выбираться в runtime.

Преимущества: соблюдение Open/Closed Principle, устранение условных операторов, гибкость выбора алгоритма.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍73🔥21
Расскажите о паттерне Singleton?

Singleton — это порождающий паттерн проектирования, который гарантирует, что у класса существует только один экземпляр, и предоставляет глобальную точку доступа к нему.

🔹 Основные характеристики:

приватный конструктор запрещает создание экземпляров извне;
статический метод getInstance() возвращает единственный экземпляр;
статическое поле для хранения экземпляра.

🔹 Когда использовать:

объект содержит глобальное состояние;
создание объекта ресурсозатратно;
нужен единый координатор действий;
логически должен быть один экземпляр.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍3🔥1
Расскажите о паттерне Adapter

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

🔹 Когда использовать:

Когда нужно использовать существующий класс, но его интерфейс не соответствует требуемому. Например, при интеграции сторонних библиотек или работе с легаси-кодом.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1🤔1
Расскажите о паттерне Factory Method

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

🔹 Когда использовать:

Когда заранее неизвестны типы и зависимости объектов, или когда нужно делегировать создание объектов подклассам.

🔹 Как работает:

Создается абстрактный метод для создания объектов, а конкретные подклассы переопределяют его, возвращая нужные типы.

🔹 Плюсы:

избавляет от привязки к конкретным классам;
упрощает добавление новых типов продуктов;
следует Open/Closed Principle.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍63🔥1
Расскажите о паттерне Abstract Factory

Abstract Factory — это порождающий паттерн, который создает семейства связанных объектов без привязки к конкретным классам.
Простыми словами: вы создаете не один объект, а целый набор совместимых между собой объектов.

▪️ Пример:

Система уведомлений, которая работает с разными провайдерами (AWS, Firebase). Для каждого провайдера нужны свои клиенты для отправки email, SMS и push-уведомлений.

// Абстрактные продукты
interface EmailSender {
void send(String to, String message);
}

interface SmsSender {
void send(String phone, String message);
}

// Абстрактная фабрика
interface NotificationFactory {
EmailSender createEmailSender();
SmsSender createSmsSender();
}

// AWS реализация
class AwsEmailSender implements EmailSender {
public void send(String to, String message) {
System.out.println("Отправка через AWS SES: " + to);
}
}

class AwsSmsSender implements SmsSender {
public void send(String phone, String message) {
System.out.println("Отправка через AWS SNS: " + phone);
}
}

class AwsNotificationFactory implements NotificationFactory {
public EmailSender createEmailSender() {
return new AwsEmailSender();
}

public SmsSender createSmsSender() {
return new AwsSmsSender();
}
}

// Аналогично FirebaseNotificationFactory...

// Использование
NotificationFactory factory = new AwsNotificationFactory();
EmailSender email = factory.createEmailSender();
SmsSender sms = factory.createSmsSender();
// Гарантия: оба сервиса работают через AWS


▪️ В чем отличие от Factory Method

— Factory Method создает один продукт
— Abstract Factory создает семейство продуктов (email + sms + push)

▪️ Когда использовать

Когда нужны наборы связанных объектов, которые должны работать вместе (клиенты для разных облаков, драйверы БД, парсеры форматов).

▪️ Минус

Сложно добавить новый тип продукта — придется менять все фабрики.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2🔥1
Расскажите о паттерне Prototype

Prototype — это порождающий паттерн, который позволяет копировать объекты, не вдаваясь в подробности их реализации.

Простыми словами: вместо создания объекта с нуля через конструктор, вы клонируете уже существующий экземпляр.

▪️ Пример:

Система отчетов, где базовая конфигурация отчета сложная (подключение к БД, загрузка шаблонов, настройка форматирования). Вместо каждый раз создавать отчет заново, клонируем прототип.
// Прототип
abstract class Report implements Cloneable {
protected String template;
protected DatabaseConnection dbConnection;
protected Map<String, Object> settings;

// Сложная инициализация
public Report() {
this.dbConnection = new DatabaseConnection(); // затратная операция
this.settings = loadDefaultSettings(); // загрузка из файла
}

@Override
public Report clone() {
try {
Report cloned = (Report) super.clone();
// Глубокое копирование для изменяемых полей
cloned.settings = new HashMap<>(this.settings);
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}

abstract void generate();
}

class SalesReport extends Report {
void generate() {
System.out.println("Генерация отчета по продажам");
}
}

// Использование
Report prototype = new SalesReport(); // долгая инициализация

// Быстрое создание копий
Report report1 = prototype.clone();
Report report2 = prototype.clone();
report2.settings.put("period", "Q2"); // изменяем только нужные параметры


▪️ Когда использовать

Создание объекта затратно (сложная инициализация, обращение к БД, парсинг файлов)
Нужно избежать привязки к конкретным классам при создании копий
Объекты различаются только состоянием, а не поведением

▪️ Важно: Shallow vs Deep Copy

Shallow copy — копируются только примитивы, ссылки на объекты остаются теми же
Deep copy — создаются копии вложенных объектов

▪️ Альтернативы clone()

— Copy constructor: new Report(original)
— Статический метод: Report.copy(original)
— Сериализация: для очень сложных объектов

▪️ Минус

Клонирование объектов с циклическими ссылками может быть сложным.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41🔥1
Расскажите о паттерне Flyweight

Flyweight — это структурный паттерн, который позволяет вместить большее количество объектов в отведённую оперативную память за счёт разделения общего состояния между объектами.

Простыми словами: вместо создания тысяч похожих объектов, вы создаёте несколько объектов-легковесов с общими данными и передаёте уникальные данные извне при использовании.

▪️ Пример

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

// Flyweight — легковес с общим состоянием
class CharacterStyle {
private final String font; // внутреннее состояние
private final int size; // (intrinsic)
private final String color;
public CharacterStyle(String font, int size, String color) {
this.font = font;
this.size = size;
this.color = color;
}

public void render(char character, int x, int y) { // внешнее состояние
System.out.println("Рендер '" + character +
"' в позиции (" + x + "," + y + ")");
}
}
// Фабрика для переиспользования flyweight-объектов
class StyleFactory {
private Map<String, CharacterStyle> styles = new HashMap<>();
public CharacterStyle getStyle(String font, int size, String color) {
String key = font + size + color;
return styles.computeIfAbsent(key,
k -> new CharacterStyle(font, size, color));
}
}
// Использование
StyleFactory factory = new StyleFactory();
// Миллион символов используют всего несколько объектов стилей
CharacterStyle arial12 = factory.getStyle("Arial", 12, "black");
arial12.render('H', 0, 0);
arial12.render('e', 10, 0);
arial12.render('l', 20, 0);
arial12.render('l', 30, 0);
arial12.render('o', 40, 0);


▪️ Когда использовать


Приложение создаёт огромное количество однотипных объектов
Объекты потребляют много памяти
Большую часть состояния можно вынести за пределы объекта
Приложение не зависит от идентичности объектов (можно переиспользовать)

▪️ Минусы

Усложнение кода из-за разделения состояния
Flyweight должен быть immutable для безопасного переиспользования

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍21
Расскажите о паттерне Builder

Builder — это порождающий паттерн, который позволяет создавать сложные объекты пошагово, разделяя процесс конструирования и представление.

Простыми словами: вместо конструктора с десятком параметров, вы собираете объект по частям, вызывая понятные методы.

▪️ Пример:

HTTP-клиент с множеством необязательных настроек: таймауты, заголовки, ретраи, прокси. Конструктор с 10 параметрами нечитаем, а Builder решает это.

public class HttpClient {
private final String baseUrl;
private final int connectTimeout;
private final int readTimeout;
private final Map<String, String> headers;
private final int maxRetries;

private HttpClient(Builder builder) {
this.baseUrl = builder.baseUrl;
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
this.headers = builder.headers;
this.maxRetries = builder.maxRetries;
}

public static class Builder {
private final String baseUrl; // обязательный
private int connectTimeout = 5000; // значение по умолчанию
private int readTimeout = 10000;
private Map<String, String> headers = new HashMap<>();
private int maxRetries = 3;

public Builder(String baseUrl) {
this.baseUrl = baseUrl;
}

public Builder connectTimeout(int ms) {
this.connectTimeout = ms;
return this;
}

public Builder readTimeout(int ms) {
this.readTimeout = ms;
return this;
}

public Builder header(String key, String value) {
this.headers.put(key, value);
return this;
}

public Builder maxRetries(int retries) {
this.maxRetries = retries;
return this;
}

public HttpClient build() {
return new HttpClient(this);
}
}
}

// Использование
HttpClient client = new HttpClient.Builder("https://api.example.com")
.connectTimeout(3000)
.header("Authorization", "Bearer token")
.maxRetries(5)
.build();


▪️ Когда использовать

Объект имеет множество параметров (особенно необязательных)
Нужна immutable-объект с удобным созданием
Хотите избежать telescoping constructor (конструктор в конструкторе)

▪️ Builder vs конструктор

— Конструктор: подходит, если параметров 2–3 и все обязательные
— Builder: если параметров больше 4 или есть необязательные

▪️ Минус

Дублирование полей между классом и билдером. Lombok @Builder решает это автоматически.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥1
Расскажите о паттерне Bridge

Bridge — это структурный паттерн, который разделяет абстракцию и реализацию так, чтобы они могли изменяться независимо друг от друга.

Простыми словами: вместо одной толстой иерархии наследования вы разбиваете её на две независимые — «что делать» и «как делать» — и связываете их композицией.

▪️ Пример:

Система отправки уведомлений: типы уведомлений (срочное, обычное) × каналы доставки (email, SMS, push). Без Bridge это 6 классов, с каждым новым каналом — взрывной рост.

// Реализация — «как доставить»
interface MessageSender {
void send(String message, String recipient);
}

class EmailSender implements MessageSender {
public void send(String message, String recipient) {
System.out.println("Email → " + recipient + ": " + message);
}
}

class SmsSender implements MessageSender {
public void send(String message, String recipient) {
System.out.println("SMS → " + recipient + ": " + message);
}
}

// Абстракция — «что отправить»
abstract class Notification {
protected MessageSender sender; // мост к реализации

public Notification(MessageSender sender) {
this.sender = sender;
}

abstract void notify(String recipient, String message);
}

class UrgentNotification extends Notification {
public UrgentNotification(MessageSender sender) {
super(sender);
}

void notify(String recipient, String message) {
sender.send("[СРОЧНО] " + message, recipient);
sender.send("[СРОЧНО] Повторное напоминание: " + message, recipient);
}
}

class RegularNotification extends Notification {
public RegularNotification(MessageSender sender) {
super(sender);
}

void notify(String recipient, String message) {
sender.send(message, recipient);
}
}

// Использование — любая комбинация
Notification urgentSms = new UrgentNotification(new SmsSender());
urgentSms.notify("+79991234567", "Сервер упал");

Notification regularEmail = new RegularNotification(new EmailSender());
regularEmail.notify("dev@company.com", "Деплой завершён");


▪️ Когда использовать

Есть две ортогональные оси изменения (тип × реализация)
Хотите избежать «взрыва» подклассов
Нужно переключать реализацию в runtime

▪️ Bridge vs Strategy

— Strategy: меняет один алгоритм внутри объекта
— Bridge: разделяет целые иерархии абстракции и реализации

▪️ Минус

Усложняет код, если оси изменения всего одна — тогда достаточно обычного полиморфизма.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍53🔥1
Расскажите о паттерне Composite

Composite — это структурный паттерн, который позволяет сгруппировать объекты в древовидную структуру и работать с ней так же, как с единичным объектом.

Простыми словами: файл и папка с файлами обрабатываются одинаково — у обоих можно спросить размер, удалить, переместить.

▪️ Пример:

Структура отдела в компании: сотрудник и команда состоят в одной иерархии. Нужно посчитать общую зарплату по любой ветке.

// Общий интерфейс
interface OrganizationUnit {
String getName();
long getSalary();
}

// Лист — отдельный сотрудник
class Employee implements OrganizationUnit {
private final String name;
private final long salary;

public Employee(String name, long salary) {
this.name = name;
this.salary = salary;
}

public String getName() { return name; }
public long getSalary() { return salary; }
}

// Композит — отдел, содержит другие элементы
class Department implements OrganizationUnit {
private final String name;
private final List<OrganizationUnit> units = new ArrayList<>();

public Department(String name) {
this.name = name;
}

public void add(OrganizationUnit unit) {
units.add(unit);
}

public String getName() { return name; }

public long getSalary() {
return units.stream()
.mapToLong(OrganizationUnit::getSalary)
.sum();
}
}

// Использование
Department dev = new Department("Разработка");
dev.add(new Employee("Анна", 200_000));
dev.add(new Employee("Борис", 180_000));

Department company = new Department("Компания");
company.add(dev);
company.add(new Employee("CEO Иван", 500_000));

System.out.println(company.getSalary()); // 880000


▪️ Когда использовать

Данные образуют древовидную структуру (файловая система, меню, оргструктура)
Клиентский код должен одинаково работать с простыми и составными объектами

▪️ Минус

Трудно ограничить типы компонентов внутри композита — приходится проверять в runtime.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍51🔥1