16 observer mode

Posted by NTM on Thu, 27 Jan 2022 03:49:37 +0100

Weather forecast demand

Specific requirements are as follows:

● 1) the weather station can publish the daily measured temperature, humidity, air pressure, etc. in the form of announcement (for example, to its own website or a third party)
● 2) it is necessary to design an open API so that other third parties can access the weather station to obtain data
● 3) provide interfaces for temperature, air pressure and humidity
● 4) when the measurement data is updated, it shall be able to notify the third party in real time

General scheme of weather forecast demand scheme

WeatherData class

Through the analysis of the weather station project, we can preliminarily design a WeatherData class

● 1) through getXxx method, the third party can access and get relevant information
● 2) when the data is updated, the weather station calls dataChange() to update the data. When the third party obtains it again, it can get the latest data. Of course, it can also be pushed


Current conditions can be understood as the website of our Meteorological Bureau

Core code

Meteorological Website

/**
 * @ClassName CurrentConditions
 * @author: shouanzh
 * @Description Display the current weather: it can be understood as the website of the Meteorological Bureau
 * @date 2022/1/26 21:12
 */
public class CurrentConditions {
    private Float temperature;
    private Float pressure;
    private Float humidity;

    /**
     * The weather condition is updated by pushing and called by WeatherData
     *
     * @param temperature
     * @param pressure
     * @param humidity
     */
    public void update(Float temperature, Float pressure, Float humidity) {
        // Update the latest weather data
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        // Display the latest weather data
        display();
    }

    /**
     * The bulletin board shows the weather
     */
    public void display() {
        System.out.println("============Latest weather============");
        System.out.println("*** Current temperature:" + this.temperature + " ℃ ***");
        System.out.println("*** Current air pressure:" + this.pressure + " kPa ***");
        System.out.println("*** Current humidity:" + this.humidity + " %RH ***");
    }

}

Meteorological data

/**
 * @ClassName WeatherData
 * @author: shouanzh
 * @Description
 *  Core class
 *  1,Contains the latest weather information
 *  2,Object containing CurrentConditions
 *  3,When the data is updated, actively call the update() method of CurrentConditions
 * @date 2022/1/26 21:13
 */
public class WeatherData {

    private Float temperature;
    private Float pressure;
    private Float humidity;
    private CurrentConditions conditions;

    /**
     * Pass in CurrentConditions object
     *
     * @param conditions
     */
    public WeatherData(CurrentConditions conditions) {
        this.conditions = conditions;
    }

    public Float getTemperature() {
        return temperature;
    }

    public Float getPressure() {
        return pressure;
    }

    public Float getHumidity() {
        return humidity;
    }

    /**
     * Push weather data to website
     */
    public void dataChange() {
        conditions.update(getTemperature(), getPressure(), getHumidity());
    }

    /**
     * Update when the weather data changes
     *
     * @param temperature
     * @param pressure
     * @param humidity
     */
    public void setData(Float temperature, Float pressure, Float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        dataChange();
    }

}

test

/**
 * @ClassName client
 * @author: shouanzh
 * @Description Client
 * @date 2022/1/26 21:14
 */
public class Client {

    public static void main(String[] args) {
        // Create weather site object
        CurrentConditions currentConditions = new CurrentConditions();
        // Create a meteorological data object and transfer it to the meteorological website object
        WeatherData weatherData = new WeatherData(currentConditions);
        // Update the latest meteorological data when the weather changes
        weatherData.setData(10f, 150f, 40f);
        weatherData.setData(15f, 130f, 60f);
        //weatherData.setData(13f, 160f, 20f);
    }

}

problem analysis
● 1) access of other third parties to meteorological stations to obtain data
● 2) unable to dynamically add a third party (Sina website) at runtime
● 3) violation of OCP principle = > observer mode

When adding a third party to WeatherData, you need to create a corresponding third-party platform object and add it to the dataChange() method, which is neither dynamic nor conducive to maintenance

Observer mode principle

The observer model is similar to the milk ordering business

● 1) milk station / Meteorological Bureau: Subject
● 2) user / third party website: Observer

Subject: registration, removal and notification


● 1) registerObserver(): Register
● 2) removeObserver(): remove
● 3) notifyObservers(): notify all registered users. According to different needs, it can update data for users to retrieve, or push, depending on the specific needs

Observer: receive input

Observer mode: a design scheme of many to one dependency between objects. The dependent object is Subject, the dependent object is observer, and the Subject notifies the observer of the change. For example, the milk station here is Subject, which is one of 1. The user is observer, which is one of many users.

Observer model of weather forecast demand scheme

UML class diagram

Core code

Observer object

/**
 * @ClassName Observer
 * @author: shouanzh
 * @Description Observer interface
 * @date 2022/1/26 22:12
 */
public interface Observer {

    void update(Float temperature, Float pressure, Float humidity);

}

/**
 * @ClassName CurrentConditions
 * @author: shouanzh
 * @Description Observer implementation
 * @date 2022/1/26 22:19
 */
public class CurrentConditions implements Observer{

    private Float temperature;
    private Float pressure;
    private Float humidity;


    @Override
    public void update(Float temperature, Float pressure, Float humidity) {
        // Update the latest weather data
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        // Display the latest weather data
        display();
    }

    /**
     * The bulletin board shows the weather
     */
    public void display() {
        System.out.println("============Latest weather============");
        System.out.println("*** Current temperature:" + this.temperature + " ℃ ***");
        System.out.println("*** Current air pressure:" + this.pressure + " kPa ***");
        System.out.println("*** Current humidity:" + this.humidity + " %RH ***");
    }
}

Subject object

/**
 * @ClassName Subject
 * @author: shouanzh
 * @Description Principal object interface
 * @date 2022/1/26 22:11
 */
public interface Subject {

    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObservers();

}

/**
 * @ClassName WeatherData
 * @author: shouanzh
 * @Description Principal object implementation
 * @date 2022/1/26 22:14
 */
public class WeatherData implements Subject{

    private Float temperature;
    private Float pressure;
    private Float humidity;
    private final List<Observer> observerList;

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

    public Float getTemperature() {
        return temperature;
    }

    public Float getPressure() {
        return pressure;
    }

    public Float getHumidity() {
        return humidity;
    }

    /**
     * Push weather data to website
     */
    public void dataChange() {
        notifyObservers();
    }

    /**
     * Update when the weather data changes
     *
     * @param temperature
     * @param pressure
     * @param humidity
     */
    public void setData(Float temperature, Float pressure, Float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        dataChange();
    }


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

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

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

test

/**
 * @ClassName Client
 * @author: shouanzh
 * @Description Client
 * @date 2022/1/26 22:21
 */
public class Client {

    public static void main(String[] args) {
        // Create weather site object
        CurrentConditions currentConditions = new CurrentConditions();
        // Create meteorological data object
        WeatherData weatherData = new WeatherData();
        // Register meteorological website object
        weatherData.registerObserver(currentConditions);
        // Update the latest meteorological data when the weather changes
        weatherData.setData(10f, 150f, 40f);
        //============Latest weather============
        //***Current temperature: 10.0 ℃***
        //***Current air pressure: 150.0 kPa***
        //***Current humidity: 40.0% RH***
    }

Benefits of observer mode
● 1) after the Observer mode is designed, the user Observer will be managed in a collective way, including registration, removal and notification
● 2) in this way, when we add observers (which can be understood as a new bulletin board here), we do not need to modify the core class WeatherData, do not modify the code, and abide by the ocp principle

For example, we have added two tripartite websites, SinaWebSite and BaiDuWebSite, which interface with the Meteorological Bureau. At this time, the three parties only need to implement the corresponding interface, and WeatherData does not need any change

/**
 * @ClassName SinaWebSite
 * @author: shouanzh
 * @Description Observer implementation
 * @date 2022/1/26 22:19
 */
public class SinaWebSite implements Observer {
    private Float temperature;
    private Float pressure;
    private Float humidity;

    /**
     * The weather condition is updated by pushing and called by WeatherData
     *
     * @param temperature
     * @param pressure
     * @param humidity
     */
    @Override
    public void update(Float temperature, Float pressure, Float humidity) {
        // Update the latest weather data
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        // Display the latest weather data
        display();
    }

    /**
     * The bulletin board shows the weather
     */
    public void display() {
        System.out.println("============Sina.com-Latest weather============");
        System.out.println("*** Sina.com-Current temperature:" + this.temperature + " ℃ ***");
        System.out.println("*** Sina.com-Current air pressure:" + this.pressure + " kPa ***");
        System.out.println("*** Sina.com-Current humidity:" + this.humidity + " %RH ***");
    }
}

test

/**
 * @ClassName Client
 * @author: shouanzh
 * @Description Client
 * @date 2022/1/26 22:21
 */
public class Client {

    public static void main(String[] args) {
        // Create weather site object
        CurrentConditions currentConditions = new CurrentConditions();
        // Create meteorological data object
        WeatherData weatherData = new WeatherData();
        // Register meteorological website object
        weatherData.registerObserver(currentConditions);
        weatherData.registerObserver(new SinaWebSite());
        // Update the latest meteorological data when the weather changes
        weatherData.setData(10f, 150f, 40f);
        //============Latest weather============
        //***Current temperature: 10.0 ℃***
        //***Current air pressure: 150.0 kPa***
        //***Current humidity: 40.0% RH***
        //============Sina.com - latest weather============
        //***Sina.com - current temperature: 10.0 ℃***
        //***Sina.com - current air pressure: 150.0 kPa***
        //***Sina.com - current humidity: 40.0% RH***
    }

}

Topics: Design Pattern