Observer Pattern

This article will be pretty short.

Imagine you have a weather station and you should provide weather info for other businesses and government alerting system (they will use this information for informing people).

For implementing this we will use Observer pattern. Observer pattern has two parts Observable and Observer.

Observable is the weather station that sends WeatherInfo to subscribers.

interface Observable {

    void add(Observer observer);

    void remove(Observer observer);

    void sendNotification(T notification);
}

This the data class that will be sent by weather station to Observers:

class WeatherInfo {
    private final Instant date;
    private final int temperature;
    private final int humidity;

    WeatherInfo(Instant date,
        int temperature,
        int humidity) {
        this.date = date;
        this.temperature = temperature;
        this.humidity = humidity;
    }

    Instant getDate() {
        return date;
    }

    int getTemperature() {
        return temperature;
    }

    int getHumidity() {
        return humidity;
    }

    @Override
    public String toString() {
        return "WeatherInfo{" + "date=" + date + ", temperature=" + temperature + ", humidity=" + humidity + '}';
    }
}

And the Observable (it is generic in our case, but really could be called WeatherStation in this concrete example):

class ObservableImpl implements Observable {

    List> observers = new ArrayList<>();

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

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

    @Override
    public void sendNotification(T notification) {
        observers.forEach(observer -> observer.notify(notification));
    }
}

Let’s see how Observers are implemented:

interface Observer {

    void notify(T notification);
}

As we said earlier there are at least two types of systems that are interested in data provided by our weather station, AlertSystem used by the government and InfoSystem used by some private companies for building devices with displays – they are Observers waiting to received data from Observable (WeatherStation):

AlertSystems reacts only defined threshold is violated:

class AlertsSystem implements Observer {

    private final int minTemperature;
    private final int maxTemperature;

    AlertsSystem(int minTemperature, int maxTemperature) {
        this.minTemperature = minTemperature;
        this.maxTemperature = maxTemperature;
    }

    @Override
    public void notify(WeatherInfo notification) {
        if (notification.getTemperature() > maxTemperature || notification.getTemperature() < minTemperature) {
            System.out.println(String.format("ALERT: On %s, temperature will be: %d", notification.getDate(),
                notification.getTemperature()));
        }
    }
}

InfoSystem displays available information to end-user:

class InfoSystem implements Observer {

    @Override
    public void notify(WeatherInfo notification) {
        System.out.println(String.format("Weather information for %s, temperature=%s C, humidity=%d%%",
            notification.getDate(), notification.getTemperature(), notification.getHumidity()));
    }
}

Now let's see the WeatherStation (Observable) that will notify daily AlertSystem and InfoSystem (Observers):

class Main {
    public static void main(String[] args) {
        Observable weatherStation = new ObservableImpl<>();
        AlertsSystem alertsSystem = new AlertsSystem(0, 35);
        InfoSystem infoSystem = new InfoSystem();

        weatherStation.add(infoSystem);
        weatherStation.add(alertsSystem);

        //weather station reads info from sensors and notifies subscribers
        WeatherInfo monday = new WeatherInfo(LocalDate.parse("2020-03-27")
            .atStartOfDay(ZoneId.systemDefault()).toInstant(), -1, 75);
        weatherStation.sendNotification(monday);

        WeatherInfo thursday = new WeatherInfo(LocalDate.parse("2020-03-28")
            .atStartOfDay(ZoneId.systemDefault()).toInstant(), 4, 75);
        weatherStation.sendNotification(thursday);

        WeatherInfo wednesday = new WeatherInfo(LocalDate.parse("2020-03-29")
            .atStartOfDay(ZoneId.systemDefault()).toInstant(), 37, 75);
        weatherStation.sendNotification(wednesday);
    }
}

Output produced by this code:

Weather information for 2020-03-26T22:00:00Z, temperature=-1 C, humidity=75%
ALERT: On 2020-03-26T22:00:00Z, temperature will be: -1
Weather information for 2020-03-27T22:00:00Z, temperature=4 C, humidity=75%
Weather information for 2020-03-28T22:00:00Z, temperature=37 C, humidity=75%
ALERT: On 2020-03-28T22:00:00Z, temperature will be: 37

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *

Acest site folosește Akismet pentru a reduce spamul. Află cum sunt procesate datele comentariilor tale.