d
WE ARE EXPERTS IN TECHNOLOGY

Let’s Work Together

n

StatusNeo

Observer Design Pattern

It defines a one-to-many dependency between objects, so that when one object change state, all of its dependents are notified and updated automatically.

Prior going for a solution, we should understand the problem by taking an Weather monitoring application. If you only concern about the solution, directly jump to solution part.

So this blog has two parts
* Problem Part
* Solution Part

Problem Part

Business Requirement

Design an internet based weather monitoring application.

We have an existing application “Weather Station”, which tracks current weather conditions by the help of physical sensors. We’d like to create an application that initially provide three display elements: Current condition, Weather statistic and Simple forecast.

Further, this is an expandable weather station and wants to release an API. So that other developers can create and plug their own display in future.

Weather station will provide Weather data object which has temperature, humidity and barometric pressure details.

As per “Weather Station” technical team, they will call WeatherData class whenever there will be change in any state(temperature, humidity and barometric pressure).

Development team had a discussion and come with below object oriented approach by defining WeatherData class, which will be directly creating instance of concrete classes and invoke their respective methods.

WeatherData design is okay as per current requirement, somehow it will create a mess in future for sure.

Reason : It’s not Expandable, as for future displays object existing will invoke their respective methods and dev team need to rewrite logic in measurementChanged method. Plus if at any time any of display need to remove still need to rewrite logic.

Solution Part

Design Principle: Strive for loosely coupled designs between objects that interacts.

Now the time has come where we need to understand Observer pattern.

Publisher + Subscriber = Observer Pattern

Subject object holds the state, when any change in the state it will automatically notify the dependent objects.

Just think like newspaper subscriptions, you pretty much understand the observer pattern where, newspaper is like a subject object, newspaper vendor act as an publisher and we are subscriber. And we can register or remove newspaper subscription anytime.

Observer Pattern UML Design Diagram

Code Base

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

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

interface DisplayElement {
    void display();
}

class WeatherData implements Subject {

    private float temperature, humidity, pressure;
    private List<Observer> observers;

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

    public void measurementChanged() {
        notifyObserver();
    }

    public void setMeasurement(float temperature, float humidity, float pressure) {
       this.temperature = temperature;
       this.humidity = humidity;
       this.pressure = pressure;
       measurementChanged();
    }

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

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

    @Override
    public void notifyObserver() {
        observers.forEach(observer -> observer.update(temperature, humidity, pressure));
    }
}

class CurrentConditionDisplay implements Observer, DisplayElement {

    private float temperature, humidity;
    private Subject weatherData;

    public CurrentConditionDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

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

    @Override
    public void display() {
        System.out.println("Current Condition :: temperature : " + temperature + " humidity : " + humidity);
    }
}

class StatisticDisplay implements Observer, DisplayElement {

    private float temperature, pressure;
    private Subject weatherData;

    public StatisticDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

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

    @Override
    public void display() {
        System.out.println("Statistic :: temperature : " + temperature + " pressure : " + pressure);
    }
}

Add Comment