Yesterday, I summarized and digested the strategy mode. Students who need to see can see my design mode First blog post . Today, we continue to explain the observer mode in HeadFirst. Firstly, the definition of observer pattern is given.
Observer mode
definition:
The observer pattern defines one to many dependencies between objects. In this way, when an object changes state, all its dependencies will be notified and updated automatically.
The Observer mode starts with the publisher (Subject) + subscriber (Observer) = observer pattern
Its class diagram is as follows:
As shown in the class diagram, the observer pattern has the following roles:
- Subject interface: the abstract topic is the publisher in our formula. The abstract topic role saves observer objects in a collection. Each topic can have any number of observers. The abstract topic provides an interface to add and remove observer objects.
- ConcreteSubject: a specific observed subject. The specific subject stores the relevant state into the specific observer object. When the internal state of the specific subject changes, it sends a notification to all internally registered observers and calls their update() method.
- Observer: Abstract observer interface, which defines an update interface to change its state when notified of topic change.
- ConcreteObserver: a concrete observer, which implements the abstract and implements the defined update interface, so as to update its own state when notified of subject change.
Observer mode implementation case
Now we have the following requirements. We need to build a weather station and use the WeatherData object to track the current weather conditions (temperature, humidity and air pressure). Now we have three kinds of bulletin boards to track and display the detected weather conditions in real time, and this must be an expandable weather station, because we may add more bulletin boards.
This case is very applicable to our observer model:
public interface WeatherData { void getTemperature(); void getHumidity(); void getPressure(); //The above three methods return the latest meteorological detection data respectively, //We don't care how these variables are set, we only care about how to the trend line when the measurement changes, //Let the bulletin board update in real time void measureMentsChanged(); }
Let's use the observer pattern. First, we implement the topic interface according to the class diagram
public interface Subject{ void registerObserver(Observer o); void removeObserver(Observer o); //Both methods require an observer as a variable, //The observer uses to register or delete. void notifyObservers(Observer o);//This method is called to notify all observers when the topic state changes. }
The Observer interface is defined below
public interface Observer{ void update(float temp,float humidity,float pressure);//When meteorological observations change, the topic treats these states as //Method, passed to the observer. All observers must implement the update() method and have implemented the observer interface. }
The bulletin board interface is defined below
public interface DisplayElement{ void display(); //The DisplayElement interface contains only one method, //That is, display(). This method is called when the bulletin board needs to be displayed. }
Next, we implement WeatherData, which is also our specific implementation Subject
public class WeatherData implements Subject{ //weatherData is a concrete observed object, so it implements the Subject interface private ArrayList<Observer> observers; //Use this list to record all observers who observe the topic private float temperature; private float humidity; private float pressure; public WeatherData(){ observers = new ArrayList<>(); } @Override public void registerObserver(Observer o) { observers.add(o); //When a new observer comes to observe the topic, register the observer into the list of observers observing the topic } @Override public void removeObserver(Observer o) { int i = observers.indexOf(o); if(i >= 0){ observers.remove(o); //When an observer no longer wants to observe the topic, delete the observer } } @Override public void notifyObservers() { for (Observer observer : observers) { observer.update(temperature,humidity,pressure); //This method notifies all observers, that is, it calls their update method } } public void messurementsChanged() { notifyObservers(); } public void setMeasurements(float temperature,float humidity,float pressure){ this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; messurementsChanged(); } }
Then implement the specific observer
public class CurrentConditionsDisplay implements Observer,DisplayElement { //This bulletin board implements the Observer interface, so it can be changed from WeatherData. It also implements the bulletin board interface private float temperature; private float humidiity; private float pressure; private Subject weatherData; public CurrentConditionsDisplay(WeatherData weatherData) { //The weatherdata object is used for registration this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void display() { System.out.println("Current conditions:" + temperature + "F degrees and pressure:" + pressure + "humidity:"+ humidiity); } @Override public void update(float temperature, float humidity, float pressure) { //When update is invoked, we save these data and then call display to display it. this.temperature = temperature; this.humidiity = humidity; this.pressure = pressure; display(); } }
We test through a specific test program:
public class WeatherStation { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay firstDisplay = new CurrentConditionsDisplay(weatherData); //Observers are registered to the observer list //secondDisplay thirdDisplay is also intended to represent three specific observers. I didn't implement it, which is similar to firstDisplay weatherData.setMeasurements(80,65,30.4f);//Analog measurement data changes weatherData.setMeasurements(70,65,30.4f); weatherData.setMeasurements(30,65,30.4f); } } -------------------------- Operation results: Current conditions:80.0F degrees and pressure:30.4humidity:65.0 Current conditions:70.0F degrees and pressure:30.4humidity:65.0 Current conditions:30.0F degrees and pressure:30.4humidity:65.0
From the above, we can see that when our Subject changes, the observer immediately receives the notice and knows that the data in the Subject of interest has changed.
The above is the observer mode I implemented myself. The observer mode is built into the initial Java API, which is in Java Util package. The two related structures are the observer interface and the Observer class, which are similar to the Subject interface and observer implemented by ourselves. Many functions have been prepared by the Java API, which can be used conveniently.
Observed Subject
Observer
Interested students can use Java The api provided by util package is implemented.
To sum up
The observer pattern provides an object design that allows loose coupling between the subject and the observer. For everything about the observer, the subject only knows that the observer implements an interface (that is Observer Interface). The subject does not need to know who the observer's specific class is, what it has done, or any other details. Topics depend on the interface rather than the specific implementation. We can add observers at any time, and other observers and topics will not be affected. At the same time, we do not need to modify the code when we add observers. Therefore, we can reuse topics and observers independently, and the two are not tightly coupled, And make a loose coupling (changing one side does not affect the other.) Well, today's observer pattern is over. If you want to know more about design patterns, please pay attention to me~