Observer mode of design mode (25)

1, Foreword

        In the real world, many objects do not exist independently, and the behavior change of one object may lead to the behavior change of one or more other objects. For example, when the price of a commodity rises, some businesses will be happy and consumers will be sad; Also, when we drive to the intersection, we will stop at the red light and go at the green light. There are many examples, such as stock prices and stock market, WeChat official account and WeChat users, weather bureau weather forecast and listeners, thieves and police.

1.1 project requirements of weather forecast

         The specific requirements for the weather forecast project are as follows:

  1. The weather station can publish the daily measured temperature, humidity, air pressure, etc. in the form of announcement (such as to its own website or a third party).
  2. An open API needs to be designed 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.

1.2 common solutions to solve the problem of weather forecast demand

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

        explain:

  1. Through the getXxx method, the third party can access and obtain relevant information;
  2. When the data is updated, the weather station updates the data by calling dataChange(). When the third party obtains it again, it can get the latest data. Of course, it can also be pushed.  

        The specific code is as follows:

public class Client {
	public static void main(String[] args) {
		//Create accessor currentConditions
		CurrentConditions currentConditions = new CurrentConditions();
		//Create WeatherData and pass the access party currentConditions to WeatherData
		WeatherData weatherData = new WeatherData(currentConditions);
		
		//Update weather conditions
		weatherData.setData(30, 150, 40);
		
		//Changes in weather conditions
		System.out.println("============Changes in weather conditions=============");
		weatherData.setData(40, 160, 20);
		

	}
}



public class WeatherData {
	private float temperatrue;
	private float pressure;
	private float humidity;
	private CurrentConditions currentConditions;
	//Join a new third party

	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 the access Party's update
		currentConditions.update(getTemperature(), getPressure(), getHumidity());
	}

	//When the data is updated, setData is called
	public void setData(float temperature, float pressure, float humidity) {
		this.temperatrue = temperature;
		this.pressure = pressure;
		this.humidity = humidity;
		//Call dataChange to push the latest information to the access party currentConditions
		dataChange();
	}
}

/**
 * Display the current weather (it can be understood as the weather station's own website)
 * @author Administrator
 *
 */
public class CurrentConditions {
	// Temperature, air pressure, humidity
	private float temperature;
	private float pressure;
	private float humidity;

	//Weather update is called by WeatherData. I use push mode
	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 + "***");
	}
}

        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;

2, Observer mode

        Definition of observer mode: it refers to the one to many dependency relationship between multiple objects. When the state of an object changes, all objects that depend on it can be notified and updated automatically. This mode is sometimes called publish subscribe mode and model view mode. It is an object behavior mode.

         Observer mode is an object behavior mode, and its main advantages are as follows.

  1. It reduces the coupling relationship between the target and the observer, which is an abstract coupling relationship. Comply with the principle of dependency inversion.
  2. A trigger mechanism is established between the target and the observer.

         Its main disadvantages are as follows.

  1. The dependency between the target and the observer is not completely removed, and circular references may occur.
  2. When there are many observers, the announcement takes a lot of time, which affects the efficiency of the program.

2.1 structure and implementation principle of mode

         When implementing observer mode, it should be noted that the specific target object and the specific observer object cannot be called directly, otherwise they will be closely coupled, which violates the object-oriented design principle.

         The main roles of the observer model are as follows.

  • Abstract Subject role: also known as abstract target class, it provides an aggregation class for saving observer objects, methods for adding and deleting observer objects, and abstract methods for notifying all observers.
  • Concrete subject role: also known as concrete target class, it implements the notification method in the abstract target. When the internal state of the concrete subject changes, it notifies all registered observer objects.
  • Abstract Observer role: it is an abstract class or interface, which contains an abstract method to update itself. It is called when receiving the change notification of a specific topic.
  • Concrete Observer role: implement the abstract method defined in the abstract observer to update its status when notified of the change of the target.

        As shown in the figure below:

          2.2 observer model to solve the problem of weather forecast demand

        The specific code is as follows:

public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //Create a WeatherData
        WeatherData weatherData = new WeatherData();

        //Create observer
        CurrentConditions currentConditions = new CurrentConditions();
        BaiduSite baiduSite = new BaiduSite();

        //Register to weatherData
        weatherData.registerObserver(currentConditions);
        weatherData.registerObserver(baiduSite);

        //test
        System.out.println("Notify each registered observer, Look at the information");
        weatherData.setData(10f, 100f, 30.3f);


        weatherData.removeObserver(currentConditions);
        //test
        System.out.println();
        System.out.println("Notify each registered observer, Look at the information");
        weatherData.setData(10f, 100f, 30.3f);
    }

}

//Interface, let WeatherData implement it 
public interface Subject {
	
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObservers();
}


/**
 * Class is the core
 * 1. Contains the latest weather information
 * 2. Contains a collection of observers, managed using ArrayList
 * 3. When the data is updated, it will actively call ArrayList and notify all (access parties) to see the latest information
 *
 * @author maoqichuan
 */
public class WeatherData implements Subject {
    private float temperatrue;
    private float pressure;
    private float humidity;
    //Observer set
    private ArrayList<Observer> observers;
	
    //Join a new third party

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

    public float getTemperature() {
        return temperatrue;
    }

    public float getPressure() {
        return pressure;
    }

    public float getHumidity() {
        return humidity;
    }

    public void dataChange() {
        //Call the access Party's update

        notifyObservers();
    }

    //When the data is updated, setData is called
    public void setData(float temperature, float pressure, float humidity) {
        this.temperatrue = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        //Call dataChange to push the latest information to the access party currentConditions
        dataChange();
    }

    //Register an observer
    @Override
    public void registerObserver(Observer o) {
        // TODO Auto-generated method stub
        observers.add(o);
    }

    //Remove an observer
    @Override
    public void removeObserver(Observer o) {
        // TODO Auto-generated method stub
        if (observers.contains(o)) {
            observers.remove(o);
        }
    }

    //Traverse all observers and notify
    @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);
        }
    }
}


//Observer interface, implemented by observers
public interface Observer {

	void update(float temperature, float pressure, float humidity);
}

public class CurrentConditions implements Observer {

    // Temperature, air pressure, humidity
    private float temperature;
    private float pressure;
    private float humidity;

    // Weather update is called by WeatherData. I use push mode
    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 + "***");
    }
}
    
// Specific observer
public class BaiduSite implements Observer {

	// Temperature, air pressure, humidity
	private float temperature;
	private float pressure;
	private float humidity;

	// Weather update is called by WeatherData. I use push mode
	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("===Baidu website====");
		System.out.println("***Baidu website temperature : " + temperature + "***");
		System.out.println("***Baidu website pressure: " + pressure + "***");
		System.out.println("***Baidu website humidity: " + humidity + "***");
	}

}

        The specific operation results are as follows:

"C:\Program Files (x86)\Java\jdk1.8.0_151\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2020.2.3\lib\idea_rt.jar=51690:C:\Program Files\JetBrains\IntelliJ IDEA 2020.2.3\bin" -Dfile.encoding=GBK -classpath "D:\yingzi\study\Source code\B Station design mode courseware\Source note courseware\code\DesignPattern\bin;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\charsets.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\deploy.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\access-bridge-32.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\cldrdata.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\dnsns.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\jaccess.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\jfxrt.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\localedata.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\nashorn.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\sunec.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\sunjce_provider.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\sunmscapi.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\sunpkcs11.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\ext\zipfs.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\javaws.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\jce.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\jfr.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\jfxswt.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\jsse.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\management-agent.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\plugin.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\resources.jar;C:\Program Files (x86)\Java\jdk1.8.0_151\jre\lib\rt.jar;D:\yingzi\study\Source code\B Station design mode courseware\Source note courseware\code\DesignPattern\src\com\atguigu\proxy\cglib\asm-commons.jar;D:\yingzi\study\Source code\B Station design mode courseware\Source note courseware\code\DesignPattern\src\com\atguigu\proxy\cglib\asm-tree.jar;D:\yingzi\study\Source code\B Station design mode courseware\Source note courseware\code\DesignPattern\src\com\atguigu\proxy\cglib\asm.jar;D:\yingzi\study\Source code\B Station design mode courseware\Source note courseware\code\DesignPattern\src\com\atguigu\proxy\cglib\cglib-2.2.jar" com.atguigu.observer.improve.Client
 Notify each registered observer, Look at the information
***Today mTemperature: 10.0***
***Today mPressure: 100.0***
***Today mHumidity: 30.3***
===Baidu website====
***Baidu website temperature : 10.0***
***Baidu website pressure: 100.0***
***Baidu website humidity: 30.3***

Notify each registered observer, Look at the information
===Baidu website====
***Baidu website temperature : 10.0***
***Baidu website pressure: 100.0***
***Baidu website humidity: 30.3***

The process has ended,Exit code 0

2.3 use of observer mode in JDK source code

         The Observable class of Jdk uses the observer mode. Its role analysis is as follows:

  • The function and status of Observable are equivalent to the Subject we talked about earlier;
  • Observable is a class, not an interface. The core method has been implemented in the class, that is, the method of managing Observer add.. delete.. notify;
  • The function and status of Observer are equivalent to those of Observer mentioned earlier, including update;
  • The use methods of Observable and Observer are the same as those mentioned above, except that Observable is a class that implements the Observer mode through inheritance;

Keywords: Java Design Pattern

Added by Hokus on Tue, 07 Dec 2021 12:23:42 +0200