Skip to content

Observer (Наблюдатель)

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

Пример использования паттерна Observer на Java

Рассмотрим пример, в котором у нас есть система погоды. У нас будет класс WeatherData, который будет представлять данные о погоде, и несколько наблюдателей, которые будут получать обновления о погоде.

Шаг 1: Создание интерфейса наблюдателя

public interface Observer {
    void update(float temperature, float humidity, float pressure);
}

Шаг 2: Создание интерфейса субъекта

public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

Шаг 3: Реализация класса субъекта

import java.util.ArrayList;
import java.util.List;

public class WeatherData implements Subject {
    private List<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData() {
        observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    // Метод для обновления данных о погоде
    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        notifyObservers(); // Уведомляем наблюдателей об изменении
    }
}

Шаг 4: Реализация конкретных наблюдателей

public class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        display();
    }

    public void display() {
        System.out.println("Current conditions: " + temperature + "°C and " + humidity + "% humidity");
    }
}

public class StatisticsDisplay implements Observer {
    private float maxTemperature;
    private float minTemperature;
    private float temperatureSum;
    private int numReadings;

    @Override
    public void update(float temperature, float humidity, float pressure) {
        temperatureSum += temperature;
        numReadings++;
        if (temperature > maxTemperature) {
            maxTemperature = temperature;
        }
        if (temperature < minTemperature || numReadings == 1) {
            minTemperature = temperature;
        }
        display();
    }

    public void display() {
        System.out.println("Avg/Max/Min temperature: " + (temperatureSum / numReadings) + "/" + maxTemperature + "/" + minTemperature);
    }
}

Шаг 5: Использование паттерна Observer

Теперь мы можем использовать наш паттерн в коде:

public class ObserverPatternDemo {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();

        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay();

        weatherData.registerObserver(currentDisplay);
        weatherData.registerObserver(statisticsDisplay);

        // Обновляем данные о погоде
        weatherData.setMeasurements(25.0f, 65.0f, 1013.0f);
        weatherData.setMeasurements(30.0f, 70.0f, 1012.0f);
        weatherData.setMeasurements(28.0f, 90.0f, 1011.0f);
    }
}

Объяснение

  1. Интерфейс Observer: Определяет метод update(), который будет вызываться для обновления состояния наблюдателя.

  2. Интерфейс Subject: Определяет методы для регистрации, удаления и уведомления наблюдателей.

  3. Класс WeatherData: Реализует интерфейс Subject. Он хранит список наблюдателей и уведомляет их об изменениях состояния (например, при обновлении данных о погоде).

  4. Классы CurrentConditionsDisplay и StatisticsDisplay: Реализуют интерфейс Observer. Они обновляют свое состояние