Event Bus и паттерн Observer в Java: реализация слабосвязанной архитектуры

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Event Bus и паттерн Observer в Java: как построить гибкую архитектуру событий

В современной Java-разработке часто возникает необходимость уведомлять одни компоненты системы о действиях, произошедших в других, не создавая между ними жесткой зависимости. Классический паттерн Observer решает эту задачу, но его реализация вручную может привести к разрастанию кода, утечкам памяти и сложностям с отладкой. На помощь приходит Event Bus — готовая реализация паттерна "издатель-подписчик" (Publish-Subscribe), которая берет на себя управление подписками и доставкой событий.

В этой статье мы подробно разберем, что такое Event Bus, как он связан с паттерном Observer, и покажем практический пример использования популярной библиотеки greenrobot EventBus для Java-приложений. Материал будет полезен разработчикам, которые хотят создавать слабосвязанные, легко тестируемые и масштабируемые системы.

Паттерн Observer: фундамент Event Bus

Паттерн Observer определяет отношение "один ко многим" между объектами: когда один объект (издатель) меняет свое состояние, все зависимые от него объекты (подписчики) автоматически уведомляются об этом. В классической реализации издатель хранит список подписчиков и вызывает их методы напрямую.

Недостатки ручной реализации:

  • Жесткая связь: подписчик должен явно реализовывать интерфейс Observer.
  • Управление жизненным циклом: необходимо вручную отписывать подписчиков, иначе возможны утечки памяти.
  • Сложность масштабирования: при росте числа подписчиков код становится трудно поддерживать.

Event Bus решает эти проблемы, выступая в роли центрального посредника. Издатель не знает о подписчиках — он просто отправляет событие в шину. Шина сама находит всех подписчиков, зарегистрированных на этот тип события, и доставляет им сообщение.

Знакомство с greenrobot EventBus

EventBus от greenrobot — это легковесная библиотека для Java и Android, которая реализует паттерн Observer с использованием аннотаций. Она позволяет:

  • Отправлять события любых типов (POJO-классы).
  • Подписываться на события по типу класса.
  • Выбирать поток доставки: основной (UI), фоновый или пост-поток.
  • Использовать приоритеты подписчиков и отмену событий.

Пример использования EventBus

Рассмотрим простой пример: компонент SensorManager генерирует события о изменении температуры, а два других компонента — Logger и AlertSystem — реагируют на них.

Шаг 1: Определение события

Событие — это обычный Java-класс, несущий данные:

public class TemperatureEvent {
    private final double temperature;
    private final String sensorId;

    public TemperatureEvent(double temperature, String sensorId) {
        this.temperature = temperature;
        this.sensorId = sensorId;
    }

    public double getTemperature() { return temperature; }
    public String getSensorId() { return sensorId; }
}

Шаг 2: Создание подписчиков

Подписчики регистрируются в EventBus и помечают методы-обработчики аннотацией @Subscribe:

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

public class Logger {
    public void start() {
        EventBus.getDefault().register(this);
    }

    @Subscribe
    public void onTemperatureEvent(TemperatureEvent event) {
        System.out.println("[LOG] Sensor " + event.getSensorId() +
                           ": temperature is " + event.getTemperature() + "°C");
    }

    public void stop() {
        EventBus.getDefault().unregister(this);
    }
}

public class AlertSystem {
    private static final double ALERT_THRESHOLD = 50.0;

    public void start() {
        EventBus.getDefault().register(this);
    }

    @Subscribe
    public void onTemperatureEvent(TemperatureEvent event) {
        if (event.getTemperature() > ALERT_THRESHOLD) {
            System.out.println("[ALERT] OVERHEAT! Sensor " + event.getSensorId() +
                               " reports " + event.getTemperature() + "°C");
        }
    }

    public void stop() {
        EventBus.getDefault().unregister(this);
    }
}

Шаг 3: Отправка событий

Издатель просто вызывает метод post() с объектом события:

import org.greenrobot.eventbus.EventBus;

public class SensorManager {
    private final String sensorId;

    public SensorManager(String sensorId) {
        this.sensorId = sensorId;
    }

    public void readTemperature() {
        double temp = 45.0 + Math.random() * 20; // симуляция показаний
        TemperatureEvent event = new TemperatureEvent(temp, sensorId);                    

Рекомендаций