Библиотека джависта | Java, Spring, Maven, Hibernate
Все самое полезное для Java-разработчика в одном канале. Список наших каналов: https://t.me/proglibrary/9197 Для обратной связи: @proglibrary_feeedback_bot По рекламе: @proglib_adv РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4
نمایش بیشتر📈 تحلیل کانال تلگرام Библиотека джависта | Java, Spring, Maven, Hibernate
کانال Библиотека джависта | Java, Spring, Maven, Hibernate (@javaproglib) در بخش زبانی روسی بازیگری فعال است. در حال حاضر جامعه شامل 22 449 مشترک است و جایگاه 6 076 را در دسته فناوری و برنامهها و رتبه 30 004 را در منطقه روسيا دارد.
📊 شاخصهای مخاطب و پویایی
از زمان ایجاد در невідомо، پروژه رشد سریعی داشته و 22 449 مشترک جذب کرده است.
بر اساس آخرین دادهها در تاریخ 07 ژوئن, 2026، کانال فعالیت پایداری دارد. در ۳۰ روز گذشته تغییر اعضا برابر -67 و در ۲۴ ساعت گذشته برابر -7 بوده و همچنان دسترسی گستردهای حفظ شده است.
- وضعیت تأیید: تأیید نشده
- نرخ تعامل (ER): میانگین تعامل مخاطب 8.46% است و در ۲۴ ساعت نخست پس از انتشار، محتوا معمولاً 5.01% واکنش نسبت به کل مشترکان کسب میکند.
- دسترسی پستها: هر پست به طور میانگین 1 900 بازدید دریافت میکند. در اولین روز معمولاً 1 124 بازدید جمعآوری میشود.
- واکنشها و تعامل: مخاطبان بهطور فعال حمایت میکنند؛ میانگین واکنش به هر پست 13 است.
- علایق موضوعی: محتوا بر موضوعات کلیدی مانند джависта, навигация, jooq, corejava, hibernate تمرکز دارد.
📝 توضیح و سیاست محتوایی
نویسنده این فضا را محل بیان دیدگاههای شخصی توصیف میکند:
“Все самое полезное для Java-разработчика в одном канале.
Список наших каналов: https://t.me/proglibrary/9197
Для обратной связи: @proglibrary_feeedback_bot
По рекламе: @proglib_adv
РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4”
به لطف بهروزرسانیهای پرتکرار (آخرین داده در تاریخ 08 ژوئن, 2026)، کانال همواره بهروز و دارای دسترسی بالاست. تحلیلها نشان میدهد مخاطبان بهطور فعال با محتوا تعامل دارند و آن را به نقطه اثرگذاری مهم در دسته فناوری و برنامهها تبدیل کردهاند.
در حال بارگیری داده...
| تاریخ | رشد مشترکین | اشارات | کانالها | |
| 08 ژوئن | +1 | |||
| 07 ژوئن | +1 | |||
| 06 ژوئن | +5 | |||
| 05 ژوئن | 0 | |||
| 04 ژوئن | +5 | |||
| 03 ژوئن | +3 | |||
| 02 ژوئن | +4 | |||
| 01 ژوئن | +5 |
• Understand Anything — граф знаний по коду и зависимостям. • DeepTutor — open-source платформа для персонализированного обучения. • Superpowers — набор практик для системной разработки с ИИ. • Awesome Agent Skills — коллекция навыков для ИИ-агентов.📚 Ключевые работы по LLM:
• Attention Is All You Need (2017) — архитектура Transformer. • GPT-1 (2018) — начало эпохи GPT. • GPT-2 (2019) — решение новых задач без дообучения. • GPT-3 (2020) — обучение на примерах из запроса. • InstructGPT (2022) — RLHF и современные чат-боты.На курсе Роман выступает консультантом программы: помогает формировать содержание уроков с опорой на актуальные инженерные практики». Занять свое место на потоке: 👉 Курс «Разработка ИИ-агентов»
| 2 | ⚡️ Магия curl
Нужно скачать файл и продолжить загрузку после обрыва? curl -C - автоматически продолжит с того места, где остановился — не нужно качать заново.
🔹 Зачем это нужно
— Загрузка больших файлов через нестабильное соединение.
— Автоматически определяет размер уже скачанной части и продолжает.
— Работает с HTTP, FTP и даже SFTP.
🔹 Как использовать
— Скачать с возможностью продолжения: curl -C - -O https://example.com/dump.sql.gz
— С прогресс-баром: curl -C - -# -O https://example.com/large-file.tar.gz
— Ограничить скорость: curl --limit-rate 10M -O https://example.com/file.iso
— В конкретный файл: curl -C - -o backup.tar.gz https://example.com/backup
— С авторизацией: curl -C - -u user:pass -O https://repo.example.com/artifact.jar
💡 Заверни в цикл для автоматического ретрая: while ! curl -C - -O https://example.com/dump.sql.gz; do sleep 5; done — скрипт будет пытаться докачать, пока не получится.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise | 1 137 |
| 3 | 🐸Библиотека джависта
#DevLife | 1 311 |
| 4 | ⚡️ Apache Fory — 4.3k ⭐️
Стандартная Java-сериализация медленная и жирная по байтам. Берёшь Kryo → лучше, но возишься с регистрацией классов и тюнингом.
Apache Fory (бывший Fury, переименовали в 2025-м) — это сериализация, которая делает и то, и другое. Генерит сериализаторы в рантайме через JIT, использует zero-copy и даёт до 170x против JDK-сериализации. IDL не нужен:
import org.apache.fory.Fory;
import org.apache.fory.config.Language;
Fory fory = Fory.builder()
.withLanguage(Language.JAVA)
.requireClassRegistration(true)
.build();
fory.register(Order.class);
byte[] bytes = fory.serialize(order);
Order copy = (Order) fory.deserialize(bytes);
Это drop-in замена JDK / Kryo / Hessian — со 100% совместимым API (writeObject/readObject, Externalizable и т.д.), только в разы быстрее. Корректно тащит shared- и циклические ссылки, умеет schema evolution (можно добавлять/удалять поля независимо на двух концах), поддерживает GraalVM native image через AOT без рефлексии. А режим xlang сериализует один и тот же объект между Java, Python, C++, Go, Rust, JS, Scala, Kotlin и TypeScript.
Идеален для высоконагруженного RPC, кэшей, передачи данных между сервисами и кросс-язычных пайплайнов, где сериализация — это узкое место.
📱 Репозиторий
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise | 1 439 |
| 5 | 😎 Знакомьтесь с экспертом Proglib.academy: Senior Software Engineer и Team Lead в Yandex Cloud Роман Барлос
Роман — консультант нашего курса «Разработка ИИ-агентов». Он работает на стыке cloud-native архитектуры и AI, активно внедряя современные ИИ-подходы в реальные процессы разработки.
За что его ценит IT-комьюнити?
🟣 Team Lead и AI-евангелист в команде UX Yandex Cloud
14-лет в разработке. Занимается AI-адопшеном в команде Yandex Cloud, проводит мастер-классы и продвигает лучшие практики для повышения эффективности разработчиков.
🟣 Техлид Sourcecraft Code Assistant
С сильным практическим бэкграундом принимал участие как технический лид в создании мощного AI-расширения для VS Code.
🟣 Создатель полезного Open Source
Разрабатывает утилиты, которые позволяют быстро начать эксперименты с инференсом и агентами в локальном окружении: например, набор скриптов vllm-setup для быстрого запуска окружения и mini-proxy — минималистичный прокси для OpenAI API провайдеров.
🟣 Автор интерактивных ML-визуализаций
Объясняет сложные концепции наглядно. Создал серию залипательных обучающих материалов, где можно вживую пощупать работу сетей Хопфилда, машин Больцмана и VC-размерности.
Роман регулярно делится инженерными наработками, инсайтами и экспертизой в своем авторском Telegram-канале
На курсе Роман выступает консультантом программы: он помогает формировать содержание уроков с опорой на актуальные инженерные практики и жесткие требования индустрии.
Узнать больше о программе и разработке автономных систем:
👉 Курс «Разработка ИИ-агентов»
Так, продолжаем знакомить вас с командой?
👍 — Да, ждем новых лиц
🔥 — Жду полезные материалы от Романа | 1 305 |
| 6 | ✔️ Spring-тест: идемпотентность платёжного эндпоинта
Напишите защиту от двойного списания 👇
📦 Задание
Клиент при сетевом таймауте повторяет POST /payments и списание проходит дважды. Реализуйте идемпотентность по заголовку Idempotency-Key.
@PostMapping("/payments")
public PaymentResult pay(
@RequestHeader("Idempotency-Key") String key,
@RequestBody PaymentRequest request) {
// Ваша реализация
}
📋 Требования
— Повторный запрос с тем же ключом возвращает результат первого вызова и НЕ выполняет списание заново.
— Разные ключи → разные операции.
— Конкурентные запросы с одним ключом (двойной клик / параллельные ретраи) не должны привести к двойному выполнению.
— Ключ хранится с TTL (например, 24 часа).
Ставьте → 🔥, если нравится формат. Если нет → 🌚
💬 Решения под спойлер. Сравним, какое будет лучше.
🐸 Библиотека собеса по Java
#practise | 1 208 |
| 7 | 🐸Библиотека джависта
#DevLife | 1 598 |
| 8 | 👩💻 Руководство по Git
Подробная документацию по Git на русском языке. От базовых команд до продвинутых тем вроде pack-файлов, переменных окружения и внутреннего устройства Git.
Подойдёт и новичкам и тем, кто хочет глубже понимать, как Git работает под капотом.
🔗 Подробнее
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise | 1 779 |
| 9 | ⚡️ Продолжаем знакомить вас с экспертами курса AgentOps!
— Сергей Нотевский расскажет, как выстроить FinOps для AI-продуктов: оптимизировать затраты на разработку и продакшен, внедрить model routing, semantic cache и систему алертов для контроля расходов
— Эмиль Сатаев разберет Context Engineering: управление контекстом, защиту от prompt injection, работу с длинными контекстами и построение безопасного пайплайна входа для AI-систем
— Михаил Бондаревский покажет, как подготовить инфраструктуру для AI-агентов: Docker, sandboxing, streaming, docker-compose и воспроизводимое окружение для разработки и продакшена
— Мурат Хажгериев расскажет про Enterprise Integrations & MCP: когда MCP действительно нужен, как подключать внешние сервисы и реализовывать интеграции с OAuth2 delegation
— Герман Сабиров разберет Governance & Compliance для AI-систем: data flow, audit logs, требования 152-ФЗ, локализацию данных и построение compliance-подхода на уровне архитектуры
Курс для backend-разработчиков, тимлидов и LLM инженеров о том, как внедрять AI-логику в бэкенд IT-продуктов и сохранять стабильность сервиса.
👉 Изучить обновленную программу AgentOps и занять место. | 1 957 |
| 10 | 🏛 ArchUnit — 3.7k ⭐️
Кто-то дёрнул репозиторий прямо из контроллера «по-быстрому», ревьюер не заметил — и слои потекли. Документация в Confluence про это не в курсе.
ArchUnit превращает архитектурные правила в обычные unit-тесты. Он читает байткод твоих классов и проверяет зависимости, а значит, нарушение падает прямо в CI, как любой другой красный тест:
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
@Test
void controllers_must_not_touch_repositories() {
var imported = new ClassFileImporter().importPackages("com.myapp");
ArchRule rule = classes()
.that().resideInAPackage("..controller..")
.should().onlyDependOnClassesThat()
.resideOutsideOfPackage("..repository..");
rule.check(imported);
}
🔹 Из коробки:
→ проверка слоёв (layered) и onion-архитектуры одним fluent-вызовом;
→ поиск циклических зависимостей между пакетами;
→ контроль неймингов и аннотаций.
Работает с любым тест-фреймворком — JUnit, TestNG, без разницы. Для легаси есть «заморозка»: фиксируешь текущие нарушения как baseline и блокируешь только новые, разгребая старые постепенно. Можно даже задавать правила PlantUML-диаграммой и проверять код на соответствие картинке.
Версия 1.4.2, поддержка вплоть до Java 26. Идеален, когда в команде больше трёх человек и архитектуру хочется не объяснять на словах, а зафиксировать в коде.
📱 Репозиторий
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise | 1 707 |
| 11 | 🐸Библиотека джависта
#DevLife | 1 642 |
| 12 | ⚙️ HikariCP в проде: пять настроек, которые часто крутят неправильно
Пул соединений в Spring Boot работает «из коробки», поэтому в application.properties обычно либо пусто, либо строчка про размер пула. И всё хорошо ровно до первого пика, когда в логах начинает мелькать Connection is not available, request timed out after 30000ms, а сервис уходит в полупаралич: не падает, но и не работает.
Разбираем параметры, которые чаще всего настроены не так.
1️⃣ maximumPoolSize: «больше» ≠ «лучше»
Классика — поставить 100 «на всякий, у нас тысяча юзеров онлайн». Но каждый коннекшн к Postgres — это процесс на стороне БД, память, контекст транзакции. 100 параллельных запросов от одного бэкенда — это не параллельность, а очередь: CPU и диск всё равно одни.
Формула из pool sizing guide самого HikariCP: connections = (core_count * 2) + effective_spindle_count
Для 8 ядер + SSD это ~17 коннекшенов. И помни про реплики: 5 подов по 20 = 100 коннекшенов к одной базе только от этого сервиса, а у Postgres max_connections обычно 100–200. Перешагнул → FATAL: sorry, too many clients already.
Прежде чем раздувать пул, загляни в pg_stat_activity. В 9 из 10 случаев там медленные запросы без индекса, idle in transaction или локи. Больше коннекшенов = больше параллельных медленных запросов.
2️⃣ minimumIdle = maximumPoolSize, а не половине
Туториалы любят min-idle: 5 / max: 20 → «в холостом держим 5, в пик расширяемся». Звучит экономно, а на деле каждый новый коннекшн — это TCP + TLS + auth + инициализация сессии = 30–100 мс сверху на первые запросы при расширении. Спайк на старте дня → красивый пик p99 → ложный инцидент.
HikariCP проектировался как фиксированный пул. Дефолт minimumIdle == maximumPoolSize, и автор прямо просит не трогать. Хочешь экономить — уменьшай maximumPoolSize, а не разноси его с minimumIdle.
3️⃣ maxLifetime: всегда меньше любого внешнего таймаута
Дефолт 30 минут. Проблема: если что-то в инфраструктуре закроет коннекшн раньше, чем HikariCP его «состарит», ловишь Connection is closed.
А закрыть может многое:
▪️ AWS NLB — idle TCP через 350 сек
▪️ AWS ALB — 60 сек
▪️ корпоративный фаервол — 5–15 мин, без логов
▪️ PgBouncer server_idle_timeout — 600 сек
▪️ Postgres idle_in_transaction_session_timeout — нередко 10 мин
Ставь с запасом 30–60 сек меньше самого короткого внешнего таймаута. Не видишь внешних таймаутов — 300000 (5 мин) разумный дефолт.
4️⃣ keepaliveTime: чтобы коннекшн не протух в idle
Дефолт 0 → выключено. В средах с агрессивным conntrack или короткими idle-таймаутами файрвола соединение тихо рвётся, и следующий клиент получает Broken pipe / Connection reset на первом же запросе.
Включаешь — и HikariCP раз в N мс гоняет SELECT 1 по простаивающим коннекшенам.
spring.datasource.hikari:
keepalive-time: 30000 # 30 сек
max-lifetime: 300000 # keepalive ОБЯЗАТЕЛЬНО меньше
Минимум — 30 сек, меньше HikariCP проигнорит. Нагрузка копеечная: 20 коннекшенов = 40 пингов в минуту.
5️⃣ connectionTimeout: это твой SLA
Дефолт 30 сек — почти всегда абсурд. Если API должно отвечать за 500 мс, клиент через 30 сек уже давно получил 504 от ingress. А бэкенд продолжает копить запросы, потоки висят в ожидании коннекшна, сервис застревает на минуты.
Лучше fail fast:
spring.datasource.hikari.connection-timeout: 2000 # 2 сек
Пул исчерпан → быстрый 503, очередь не растёт, алерт срабатывает сразу. Сверху можно навесить circuit breaker (Resilience4j).
⚠️ И отдельно про Actuator: /actuator/health/db дёргает базу. При исчерпанном пуле он тоже встаёт в очередь → DOWN → k8s liveness рестартит под → нагрузка переезжает на соседей → каскад. Лечится коротким connectionTimeout + liveness, который не трогает базу вообще.
И главное помни: HikariCP — это просто пул. Если в сервисе медленные запросы без индексов, ни твики таймаутов, ни раздувание пула не помогут — получишь больше параллельных медленных запросов, и база встанет ещё быстрее. Сначала pg_stat_activity, pg_stat_statements, EXPLAIN ANALYZE — потом настройка пула.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise | 1 618 |
| 13 | @Scheduled(fixedRate = 5000) — предыдущее выполнение заняло 8 секунд. Когда запустится следующее? | 1 772 |
| 14 | 🐳 Магия Docker Compose
Поменяли конфиг одного сервиса и не хотите перезапускать весь стек из 10 контейнеров? docker compose up -d --no-deps service-name пересоздаст только указанный сервис.
🔹 Зачем это нужно
— Перезапуск одного сервиса вместо всего стека экономит минуты на тяжёлых проектах.
— --no-deps не трогает зависимости, так что БД и Redis останутся на месте.
— -d запускает в фоне, терминал свободен для другой работы.
🔹 Как использовать
— Пересоздать один сервис: docker compose up -d --no-deps api
— Пересобрать и запустить: docker compose up -d --no-deps --build api
— Посмотреть логи только одного: docker compose logs -f api
— Рестарт без пересоздания: docker compose restart api
— Масштабировать: docker compose up -d --scale worker=3
💡 restart не подхватывает изменения в docker-compose.yml или Dockerfile, для этого нужен up -d. Если обновили env-переменные или порты — только up -d применит изменения.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise | 1 891 |
| 15 | 🐸Библиотека джависта
#DevLife | 1 927 |
| 16 | ⚡️ Последний шанс забрать курсы со СКИДКОЙ 40%! Прокачайте свой мозг правильно
До конца акции вы можете воспользоваться специальными ценами на самые востребованные IT-направления. Круто и выгодно прокачать свои скиллы, чтобы получить оффер, уехать на Бали и больше не быть онлайн 😎
➡️ Разработка AI-агентов — от 49 000 ₽ (вместо 69 000 ₽)
Курс про контролируемую разработку ИИ-агентов: качество, стоимость, наблюдаемость и тестирование. С первого занятия — только практическая работа.
➡️ Курс AgentOps — 129 000 ₽ (вместо 149 000 ₽)
Профессиональный трек для разработчиков и LLM инженеров о том, как правильно внедрять AI-логику в бэкенд и сохранять железную стабильность сервиса.
➡️ Математика для Data Science — от 29 990 ₽ (вместо 39 990 ₽)
Вы научитесь решать сложные математические задачи, которые дают на собеседованиях на позицию дата-сайентиста в бигтехе. Отличная база для мощного старта в DS.
➡️ Курс Специалист по ИИ — 89 000 ₽ (вместо 113 900 ₽)
Комплексная программа для получения профессии в сфере ИИ с нуля. За 8 месяцев вы соберете сильное портфолио из 5 реальных проектов и дипломной работы.
➡️ Архитектуры и шаблоны проектирования — 27 990 ₽ (вместо 37 900 ₽)
Интенсив для разработчиков, который поможет освоить основные паттерны проектирования и прокачать навыки архитектора программного обеспечения.
🌸 Выбирайте направление, оставляйте заявку на сайте распродажи, и наш менеджер подробно вас проконсультирует | 1 989 |
| 17 | 🚀 jbang — 1.8k ⭐️
Надо накидать утилиту на 30 строк, дёрнуть API, распарсить JSON, прогнать миграцию?
И вот ты уже создаёшь Maven-проект, пишешь pom.xml, городишь src/main/java/com/example/..., добавляешь зависимость, билдишь jar. Полчаса церемоний ради скрипта, который запускается один раз.
jbang убирает всё это. Один .java файл и он запускается как скрипт. Зависимости объявляются прямо в коде комментарием //DEPS, jbang сам тянет их с Maven Central, компилирует и запускает:
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.squareup.okhttp3:okhttp:4.12.0
//JAVA 21+
import okhttp3.*;
public class fetch {
public static void main(String[] args) throws Exception {
var client = new OkHttpClient();
var req = new Request.Builder()
.url("https://api.github.com/repos/jbangdev/jbang")
.build();
try (var resp = client.newCall(req).execute()) {
System.out.println(resp.body().string());
}
}
}
jbang fetch.java — и всё работает. Никакого pom.xml, никакого build-шага, никакой структуры папок.
Что ещё умеет:
— запускать скрипты прямо по URL или из GitHub Gist (jbang https://.../script.java);
— генерить нативные бинарники через GraalVM;
— ставить скрипт как системную команду (jbang app install);
— экспортить в полноценный Maven/Gradle-проект, когда прототип дорос до проекта.
Поддерживает .java, .jsh, .kt, .groovy и даже .md. А если на машине нет JDK, скачает сам.
Идеален для CLI-тулзов, автоматизации, обучения и тех моментов, когда писать Python только потому что «на Java долго» — обидно.
📱 Репозиторий
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise | 1 859 |
| 18 | 🦾🧠🏋️ Качаем мозги к лету!
Все готовятся к пляжному сезону, а мы предлагаем прокачать хард-скилы, чтобы забрать крутой оффер, строить продукты будущего и работать из любой точки мира 😎
⚡️ Распродажа @proglib_academy: забирайте самые актуальные образовательные треки по сниженным ценам!
➡️ Разработка AI-агентов — от 49 000 ₽ (вместо 69 000 ₽).
➡️ Курс AgentOps — 129 000 ₽ (вместо 149 000 ₽).
➡️ Математика для разработки AI-моделей — 23 990 ₽ (вместо 31 990 ₽).
➡️ ML для старта в Data Science — 28 990 ₽ (вместо 38 990 ₽).
Почему мы?
⭐️Учим для продакшена. Наши программы заточены под реальные задачи бизнеса: как не слить бюджет на токены, как заставить LLM работать стабильно в бэкенде и как выстроить отказоустойчивую архитектуру.
⭐️Спикеры — суровые практики. Вы будете перенимать опыт у действующих AI-архитекторов, тимлидов и ML-инженеров из топовых IT-компаний.
⭐️Комплексный подход. Мы даем как мощный математический фундамент для понимания моделей «под капотом», так и передовые инструменты оркестрации агентов.
⭐️Много практики и фидбека. Вебинары, десятки практических заданий и живое общение с экспертами в чате Telegram на протяжении всего обучения.
⏳ Оставляйте заявку и бронируйте место со СКИДКОЙ 40% | 1 775 |
| 19 | 💥 vibe coding — это не продуктивность, а технический долг с красивым названием
Я сам использую несколько ИИ-агентов, расчехлять каменный топор не предлагаю.
Но смотрю, во что превращается «просто опиши интент, а код появится». PR на 600 строк, который разраб не может объяснить на ревью. Тесты, которые проверяют, что мок вернул то, что в него замокали. «Починили» баг, а прилетело ещё два, потому что никто не читал, что там нагенерилось.
Сгенерить за минуту и разгребать месяц — это не 10x к производительности. AI это джун с бесконечной скоростью и нулевым контекстом бизнеса. Джуну ревьюишь каждую строку, а с ИИ часто выключают голову, потому что «модель же умная».
Vibe coding — это новый уровень абстракции или мы растим поколение, которое не умеет даже дебажить?
💬 Го в комменты
🐸 Библиотека джависта
#DevLife | 1 749 |
| 20 | ❓ Расскажите о паттерне Visitor
Visitor — это поведенческий паттерн, который позволяет добавлять новые операции к объектам, не изменяя их классы.
Простыми словами: налоговый инспектор (visitor) приходит в разные компании и выполняет проверку — компании не меняются, а новые виды проверок добавляются легко.
▪️ Пример:
Система документооборота: есть разные типы документов, и нужно добавлять операции (экспорт, валидация, подсчёт статистики) без изменения классов документов.
// Visitor
interface DocumentVisitor {
void visit(Invoice invoice);
void visit(Contract contract);
void visit(Report report);
}
// Элементы
interface Document {
void accept(DocumentVisitor visitor);
}
class Invoice implements Document {
private final BigDecimal amount;
public Invoice(BigDecimal amount) { this.amount = amount; }
public BigDecimal getAmount() { return amount; }
public void accept(DocumentVisitor visitor) {
visitor.visit(this); // double dispatch
}
}
class Contract implements Document {
private final LocalDate expiryDate;
public Contract(LocalDate expiryDate) { this.expiryDate = expiryDate; }
public LocalDate getExpiryDate() { return expiryDate; }
public void accept(DocumentVisitor visitor) {
visitor.visit(this);
}
}
class Report implements Document {
private final int pageCount;
public Report(int pageCount) { this.pageCount = pageCount; }
public int getPageCount() { return pageCount; }
public void accept(DocumentVisitor visitor) {
visitor.visit(this);
}
}
// Конкретный visitor — новая операция без изменения документов
class ExportVisitor implements DocumentVisitor {
public void visit(Invoice invoice) {
System.out.println("Экспорт счёта: " + invoice.getAmount() + " ₽");
}
public void visit(Contract contract) {
System.out.println("Экспорт договора до " + contract.getExpiryDate());
}
public void visit(Report report) {
System.out.println("Экспорт отчёта: " + report.getPageCount() + " стр.");
}
}
// Использование
List<Document> docs = List.of(
new Invoice(new BigDecimal("150000")),
new Contract(LocalDate.of(2027, 1, 1)),
new Report(42)
);
DocumentVisitor exporter = new ExportVisitor();
docs.forEach(doc -> doc.accept(exporter));
▪️ Когда использовать
— Нужно выполнить операцию над группой разнородных объектов
— Новые операции добавляются часто, а новые типы элементов — редко
— Пример из JDK: java.nio.file.FileVisitor
▪️ Минус
Visitor нужно обновлять при добавлении нового типа элемента — нарушается Open/Closed Principle для элементов.
🐸 Библиотека собеса по Java
#patterns | 1 540 |
اکنون در دسترس! پژوهش تلگرام ۲۰۲۵ — مهمترین بینشهای سال 
