Observer и Observable в Java: когда и зачем их использовать?
Быстрый ответ
Следует использовать шаблон Observer для разграничения компонентов: субъект уведомляет наблюдателей о любых изменениях в своем состоянии. C Java 9+ предпочтительнее применять java.beans.PropertyChangeListener
и отказаться от устаревших Observer/Observable. Для более сложных задач рекомендуется использование Reactive Streams — в этом контексте основным решением является RxJava.
Пример использования:
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class DataModel {
private String data;
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public void addListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener); // Регистрируем слушателя.
}
public void setData(String newData) {
String oldData = this.data;
this.data = newData;
pcs.firePropertyChange("data", oldData, newData); // Осуществляем уведомление слушателей об изменении.
}
}
// Применение:
DataModel model = new DataModel();
model.addListener((evt) -> System.out.println("Данные обновлены: " + evt.getNewValue())); // Подписываемся на обновления.
model.setData("UpdatedData"); // Обновляем данные.
Выбор PropertyChangeSupport
упрощает реализацию шаблона Observer: аналогично личному ассистенту, он облегчает работу с регистрацией слушателей и информированием их о произошедших изменениях.
Observer и Observable в динамических системах
Динамические системы обеспечивают идеальные условия для применения шаблона Observer, позволяя объектам своевременно реагировать на изменения в состоянии, подобно подписке на обновления в социальных сетях. В событийно-ориентированных архитектурах данный шаблон способствует синхронизации всех компонентов с изменениями в субъекте.
Масштабирование приложений через применение Observer
При масштабировании приложений применение шаблона Observer упрощает реакцию на изменения. Благодаря методам addObserver()
и deleteObserver()
, можно непринужденно добавлять либо удалять наблюдателей. Это способствует модульности и поддерживаемости кода, а лишь повышает простоту интеграции наблюдателей в глобальную систему.
Реально временные приложения
Примеры из повседневной жизни, включая обновления сервисов или уведомления активных сообществ, ярко демонстрируют эффективность шаблона Observer в контексте распространения обновлений. Опускание флага после оповещения гарантирует актуальность данных, избегая потери или дублирования уведомлений.
Визуализация
Отношение между субъектом и наблюдателями можно уподобить подписке на газету:
Наблюдаемый (📰 Газета):
- Публикует выпуски с новостями и обновлениями.
Наблюдатель (👀 Подписчик):
- Подписывается и ожидает новые выпуски.
- Получает уведомление о выходе нового выпуска.
Структура общения:
- 👀 Подписка:
Подписчик.присоединяется(Газета)
- 📰 Публикация:
Газета.публикуетВыпуск()
- 👀 Получение уведомления:
Подписчик.получаетУведомление()
В реальности:
- 📰 Газета соответствует
Observable
- 👀 Подписчик — это
Observer
- "Трансляция" информации производится согласно принципам шаблона Observer.
Наблюдатели и наблюдаемые выполняют функции источника и получателя информации соответственно, где получатели всегда в курсе последних событий.
Внедрение Observer и Observable
Шаблон Observer применим не только в контексте пользовательских интерфейсов или записи действий. Он актуален для отслеживания изменений в окружающей среде через сенсоры, следит за колебаниями цен на биржах и актуален в качестве основы для систем отчетности. Благодаря слабой связи каждый наблюдатель может сфокусироваться на своем собственном интересующем аспекте изменений.
Согласованность системы
Приоритетное значение имеет поддержание согласованности системы в реальном времени, отображая актуальное состояние всех ее составляющих. Это исключает вероятность дезинформации из-за несвоевременного обновления данных.
Гибкость уведомлений
Наблюдатели имеют полную свободу действий по отношению к реакции на уведомления: мгновенное реагирование, организация очереди для пакетной обработки или игнорирование некоторых сообщений. Это расширяет сферу применения шаблона, адаптируя его к различным обстоятельствам.
Преимущества и недостатки шаблона Observer
Не следует злоупотреблять использованием шаблона Observer, поскольку избыточные оповещения могут привести к снижению производительности системы. Осуществляйте оповещение только при фактических изменениях, проверьте требуется ли оно через setChanged()
.
Потокобезопасность
Потокобезопасность является критической при применении данного шаблона. Важно исключить возможность состояний гонки и взаимных блокировок при многопоточности. Правильная синхронизация механизмов оповещения — залог успешной реализации.
Предотвращение утечек памяти
Необходимо следить за утечками памяти. Некорректная отписка наблюдателей может привести к неоправданным затратам памяти. Используйте deleteObserver()
, чтобы прекратить связь с ненужными объектами.
Полезные материалы
- Observer (Java Platform SE 8) — документация от Oracle по интерфейсу Observer.
- Observer Design Pattern in Java | DigitalOcean — подробное руководство по реализации шаблона Observer.
- Design Patterns – Observer Pattern — руководство от TutorialsPoint с примерами шаблона Observer.
- Observer Design Pattern – GeeksforGeeks — полное введение в шаблон Observer от GeeksforGeeks.
- Observable (Java Platform SE 8) — документация Oracle по классу Observable.