Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

Project requirements for weather forecasting

  1. Weather stations can publish daily measurements of temperature, humidity, pressure, etc., in the form of announcements (such as on their own websites or third parties).
  2. Open apis need to be designed so that other third parties can access weather stations to obtain data.
  3. Provides interfaces for temperature, air pressure and humidity
  4. When measurement data is updated, third parties should be notified in real time

Through requirements analysis, we can conclude that we need a weather information class first

Because we do not know the weather information by ourselves, we access it through the third party, so we need to use getXxx method, so that the third party can access and get relevant information. When the data is updated, the weather station calls dataChange() to update the data. When the third party retrieves the data again, the latest data can be obtained, and of course can be pushed.

CurrentConditions(current weather conditions) can be understood as our bureau of Meteorology website // push

This class is our weather station class, it’s our own weather station class, we don’t design the design model, we don’t specify.

Public class CurrentConditions {// private float temperature; private float pressure; private float humidity; // Weather updates are called by WeatherData, Public void update(float temperature, float pressure, float humidity) {this.temperature = temperature; this.pressure = pressure; this.humidity = humidity; display(); } // Display public void display() {system.out.println ("***Today mTemperature: "+ temperature + "***"); System.out.println("***Today mPressure: " + pressure + "***"); System.out.println("***Today mHumidity: " + humidity + "***"); }}Copy the code

We have information retrieval classes, which are very simple to write

/** * class is the core * 1. Contains the latest weather information * 2. CurrentConditions object * 3. CurrentConditions update (with display) @author ll * */ Public class WeatherData {private float temperatrue; private float pressure; private float humidity; private CurrentConditions currentConditions; Public WeatherData(CurrentConditions CurrentConditions) {this. CurrentConditions = CurrentConditions; } public float getTemperature() { return temperatrue; } public float getPressure() { return pressure; } public float getHumidity() { return humidity; } public void dataChange() {// Call currentconditions.update (getTemperature(), getPressure(), getHumidity()); } // When data is updated, Public void setData(float temperature, float pressure, float humidity) {this.temperatrue = temperature; this.pressure = pressure; this.humidity = humidity; CurrentConditions dataChange(); currentConditions dataChange(); }}Copy the code

If we don’t use observer mode, we just use it

Public class Client {public static void main(String[] args) {// Create currentConditions currentConditions currentConditions = new CurrentConditions(); WeatherData = new WeatherData(currentConditions); // Create WeatherData and pass it to WeatherData.  // Update the weatherdata.setData (30, 150, 40); System. / / the weather change out. Println (" = = = = = = = = = = = = if weather conditions change = = = = = = = = = = = = = "); weatherData.setData(40, 160, 20); }}Copy the code

A third party can access the meteorological station to obtain data. A third party cannot be added dynamically during operation

In WeatherData, when a third party is added, a corresponding third party’s bulletin board object needs to be created and added to the dataChange, which is not conducive to maintenance or dynamic addition

First we should have a Subject that I need to be observed

RegisterObserver registered

RemoveObserver removed

NotifyObservers () notifies all registered users, either updating data for users to capture, or implementing a push, depending on their requirements

It is our observer

Observer pattern: A design scheme in which objects have multiple dependencies of one to one. The dependent object is Subject, the dependent object is Observer, and the Subject notifies the Observer of changes. For example, here the milk station is Subject, a party to 1. The user, as Observer, is the many party.

So let’s write our observation interface

Public interface Observer {public void update(float temperature, float pressure, float humidity); }Copy the code

Implementing the Observer interface

Public class CurrentConditions implements Observer {private float temperature; private float pressure; private float humidity; // Weather updates are called by WeatherData, Public void update(float temperature, float pressure, float humidity) {this.temperature = temperature; this.pressure = pressure; this.humidity = humidity; display(); } // Display public void display() {system.out.println ("***Today mTemperature: "+ temperature + "***"); System.out.println("***Today mPressure: " + pressure + "***"); System.out.println("***Today mHumidity: " + humidity + "***"); }}Copy the code

We changed the information retrieval class because of the new logic

/** * class is the core * 1. Contains the latest weather information * 2. ArrayList * 3. When data is updated, I'm going to call the ArrayList, * @author ll * */ public class WeatherData implements Subject {private float temperatrue; private float pressure; private float humidity; Private ArrayList<Observer> observers; Public WeatherData() {observers = new ArrayList<Observer>(); } public float getTemperature() { return temperatrue; } public float getPressure() { return pressure; } public float getHumidity() { return humidity; } public void dataChange() {// Update notifyObservers(); } // When data is updated, Public void setData(float temperature, float pressure, float humidity) {this.temperatrue = temperature; this.pressure = pressure; this.humidity = humidity; CurrentConditions dataChange(); currentConditions dataChange(); } @override public void registerObserver(Observer o) {// TODO auto-generated method stub attendant.add (o); @override public void removeObserver(Observer o) {// TODO auto-generated method stub if(observers.contains(o)) { observers.remove(o); }} @override public void notifyObservers() {// TODO auto-generated method stub for(int I = 0; i < observers.size(); i++) { observers.get(i).update(this.temperatrue, this.pressure, this.humidity); }}}Copy the code

Finally, it’s our call

Public class Client {public static void main(String[] args) {// TODO auto-generated method stub // Creates a WeatherData WeatherData weatherData = new WeatherData(); CurrentConditions = new CurrentConditions(); BaiduSite baiduSite = new BaiduSite(); . / / registered to weatherData weatherData registerObserver (currentConditions); weatherData.registerObserver(baiduSite); // Test system.out.println (" notify each registered observer to see the message "); WeatherData. SetData (10 f, 100 f, 30.3 f); weatherData.removeObserver(currentConditions); / / test System. Out. Println (); System.out.println(" notify each registered observer to see the message "); WeatherData. SetData (10 f, 100 f, 30.3 f); }}Copy the code

The Observer pattern is designed to manage users as a collection, including registration, removal, and notification.

This way, when we add an observer (in this case, a new bulletin board), we don’t need to change the core class WeatherData. It doesn’t change the code, following the OCP principle.