Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git на GitByBit.com! Привет! Хочешь круто подтянуть Git? Глянь мой новый курс на GitByBit.com!
Наблюдатель

Наблюдатель на Java

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

При этом наблюдатели могут свободно подписываться и отписываться от этих оповещений.

Сложность:

Популярность:

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

Примеры Наблюдателя в стандартных библиотеках Java:

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

Подписка и оповещения

В этом примере Наблюдатель используется для передачи событий между объектами текстового редактора. Всякий раз когда объект редактора меняет своё состояние, он оповещает своих наблюдателей. Объекты EmailNotificationListener и LogOpenListener следят за этими уведомлениями и выполняют полезную работу в ответ.

Классы подписчиков не связаны с классом редактора и могут быть повторно использованы в других приложениях если потребуется. Класс Editor зависит только от общего интерфейса подписчиков. Это позволяет добавлять новые типы подписчиков не меняя существующего кода редактора.

publisher

publisher/EventManager.java: Базовый издатель

package refactoring_guru.observer.example.publisher; import refactoring_guru.observer.example.listeners.EventListener; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class EventManager { Map<String, List<EventListener>> listeners = new HashMap<>(); public EventManager(String... operations) { for (String operation : operations) { this.listeners.put(operation, new ArrayList<>()); } } public void subscribe(String eventType, EventListener listener) { List<EventListener> users = listeners.get(eventType); users.add(listener); } public void unsubscribe(String eventType, EventListener listener) { List<EventListener> users = listeners.get(eventType); users.remove(listener); } public void notify(String eventType, File file) { List<EventListener> users = listeners.get(eventType); for (EventListener listener : users) { listener.update(eventType, file); } } } 

editor

editor/Editor.java: Конкретный издатель, изменение которого хотят отслеживать наблюдатели

package refactoring_guru.observer.example.editor; import refactoring_guru.observer.example.publisher.EventManager; import java.io.File; public class Editor { public EventManager events; private File file; public Editor() { this.events = new EventManager("open", "save"); } public void openFile(String filePath) { this.file = new File(filePath); events.notify("open", file); } public void saveFile() throws Exception { if (this.file != null) { events.notify("save", file); } else { throw new Exception("Please open a file first."); } } } 

listeners

listeners/EventListener.java: Интерфейс подписчиков

package refactoring_guru.observer.example.listeners; import java.io.File; public interface EventListener { void update(String eventType, File file); } 

listeners/EmailNotificationListener.java: Слушатель, рассылающий email-уведомления

package refactoring_guru.observer.example.listeners; import java.io.File; public class EmailNotificationListener implements EventListener { private String email; public EmailNotificationListener(String email) { this.email = email; } @Override public void update(String eventType, File file) { System.out.println("Email to " + email + ": Someone has performed " + eventType + " operation with the following file: " + file.getName()); } } 

listeners/LogOpenListener.java: Слушатель, записывающий лог операций

package refactoring_guru.observer.example.listeners; import java.io.File; public class LogOpenListener implements EventListener { private File log; public LogOpenListener(String fileName) { this.log = new File(fileName); } @Override public void update(String eventType, File file) { System.out.println("Save to log " + log + ": Someone has performed " + eventType + " operation with the following file: " + file.getName()); } } 

Demo.java: Клиентский код

package refactoring_guru.observer.example; import refactoring_guru.observer.example.editor.Editor; import refactoring_guru.observer.example.listeners.EmailNotificationListener; import refactoring_guru.observer.example.listeners.LogOpenListener; public class Demo { public static void main(String[] args) { Editor editor = new Editor(); editor.events.subscribe("open", new LogOpenListener("/path/to/log/file.txt")); editor.events.subscribe("save", new EmailNotificationListener("admin@example.com")); try { editor.openFile("test.txt"); editor.saveFile(); } catch (Exception e) { e.printStackTrace(); } } } 

OutputDemo.txt: Результат выполнения

Save to log \path\to\log\file.txt: Someone has performed open operation with the following file: test.txt Email to admin@example.com: Someone has performed save operation with the following file: test.txt 

Наблюдатель на других языках программирования

Наблюдатель на C# Наблюдатель на C++ Наблюдатель на Go Наблюдатель на PHP Наблюдатель на Python Наблюдатель на Ruby Наблюдатель на Rust Наблюдатель на Swift Наблюдатель на TypeScript