a schema definition
Observer pattern, also known as publish/subscribe pattern. The observer pattern defines a one-to-many dependency between objects. When the state of an object changes, all objects that depend on it are notified and updated automatically.
Two-mode example
1 Pattern Analysis
We use the Bureau of Meteorology's high temperature warning to illustrate this pattern.
2 Observer pattern static class diagram
3 Code Examples
3.1 Observer interface - IObserver
package com.demo.observer; import com.demo.subject.ISubject; /** * Observer interface * @author * */ public interface IObserver { //update method public void update(ISubject subject); }
3.2 Subject interface - ISubject
package com.demo.subject; import com.demo.observer.IObserver; /** * Subject interface (observed) * * @author * */ public interface ISubject { /** * add observer * * @param observer * @return */ public boolean add(IObserver observer); /** * delete observer * * @param observer * @return */ public boolean remove(IObserver observer); /** * Notify all observers to update data */ public void notifyAllObserver(); /** * Set temperature value * * @param temperature */ public void setTemperature(float temperature); /** * Get temperature warning * * @return */ public String temperatureReport(); }
3.3 A specific subject implements a Subject
package com.demo.subject; import java.util.Iterator; import java.util.Vector; import com.demo.observer.IObserver; /** * Subject implementation class (observed) * * @author * */ public class Subject implements ISubject { // temperature /** * (1) High temperature yellow warning signal * * Standard: The daily maximum temperature will be above 35℃ for three consecutive days. * * (2) High temperature orange warning signal * * Standard: The maximum temperature will rise above 37℃ within 24 hours. * * (3) High temperature red warning signal * * Standard: The maximum temperature will rise above 40℃ within 24 hours. */ private float temperature; // alert level private String warningLevel; // save the watcher list private final Vector<IObserver> vector; /** * The constructor initializes the observer list */ public Subject() { vector = new Vector<IObserver>(); } /** * add observer */ public boolean add(IObserver observer) { if (observer != null && !vector.contains(observer)) { return vector.add(observer); } return false; } /** * remove observer */ public boolean remove(IObserver observer) { return vector.remove(observer); } /** * Notify all observers to update data */ public void notifyAllObserver() { System.out.println("======Meteorological Department issues high temperature" + this.warningLevel + "Warning!======"); Iterator<IObserver> iterator = vector.iterator(); while (iterator.hasNext()) { (iterator.next()).update(this); } } /** * Private method to set alert level based on temperature value and notify all observers */ private void invoke() { if (this.temperature >= 35) { if (this.temperature >= 35 && this.temperature < 37) { this.warningLevel = "黄色"; } else if (this.temperature >= 37 && this.temperature < 40) { this.warningLevel = "橙色"; } else if (this.temperature >= 40) { this.warningLevel = "红色"; } // Notify all observers of temperature status this.notifyAllObserver(); } } /** * Set temperature value * * @param temperature */ public void setTemperature(float temperature) { this.temperature = temperature; this.invoke(); } /** * Get temperature warning */ public String temperatureReport() { return " 温度:" + this.temperature; } }
3.4 Personal Observer - PersonObserver
package com.demo.observer; import com.demo.subject.ISubject; /** * Individual user watchers * @author * */ public class PersonObserver implements IObserver { public void update(ISubject subject) { System.out.println("The individual received a high temperature warning: " + subject.temperatureReport()); } }
3.5 Government Observer-GovernmentObserver
package com.demo.observer; import com.demo.subject.ISubject; /** * Government User Observer * @author * */ public class GovernmentObserver implements IObserver { public void update(ISubject subject) { System.out.println("Government department received high temperature warning: " + subject.temperatureReport()); } }
3.6 Enterprise Observer - CompanyObserver
package com.demo.observer; import com.demo.subject.ISubject; /** * Enterprise user observer * @author * */ public class CompanyObserver implements IObserver { public void update(ISubject subject) { System.out.println("Enterprises and institutions received high temperature warning: " + subject.temperatureReport()); } }
3.7 Let the system start running a Client
package com.demo; import java.util.Random; import com.demo.observer.CompanyObserver; import com.demo.observer.GovernmentObserver; import com.demo.observer.PersonObserver; import com.demo.subject.ISubject; import com.demo.subject.Subject; /** * Client application * * @author * */ public class Client { /** * @param args */ public static void main(String[] args) { // create the subject object ISubject subject = new Subject(); // Add observers for enterprises and institutions subject.add(new CompanyObserver()); // Add government user observer subject.add(new GovernmentObserver()); // Add individual user observers subject.add(new PersonObserver()); Random random = new Random(); int i = 0; while (++i < 10) { // set random temperature subject.setTemperature(random.nextInt(45)); } } }
4 Running results
======The Meteorological Department issues a high temperature yellow alert!======
Enterprises and institutions receive high temperature warning: Temperature: 35.0
Government departments receive a high temperature warning: Temperature: 35.0
Individual receives high temperature warning: Temperature: 35.0
======The Meteorological Department issues a red alert for high temperature!======
Enterprises and institutions receive high temperature warning: Temperature: 43.0
Government departments receive a high temperature warning: Temperature: 43.0
Individual receives high temperature warning: Temperature: 43.0
====== Meteorological Department issues orange alert for high temperature! ======
Enterprises and institutions receive high temperature warning: Temperature: 37.0
Government departments receive a high temperature warning: Temperature: 37.0
Individual receives high temperature warning: Temperature: 37.0
Three principles of pattern design
1 "Open - closed" principle
2 Single Responsibility Principle
3 Dependency Inversion Principle
Four use cases
1 When an abstract model has two aspects, one of which depends on the other, and these two aspects need to be encapsulated into independent objects, which can be changed and reused independently of each other.
2 When the change of an object in a system needs to change the content of other objects at the same time, but it is not known how many objects to be changed.
3 When a change in an object must notify other objects to make corresponding changes, but it is not certain who the notification object is.
Five "push data" static class diagram
The so-called "push data" means that when the observed object changes, the relevant data is passed to the observer in the form of parameters, which forms the "push data" of the observed object to the observer. The static class diagram is as follows:
Six "pull data" static class diagram
The so-called "pull data", the observer object contains a reference to the instance of the observed object. When the observed object changes, it will not pass any data to the observer, and the observer will refer to the observed object instance according to the reference of the observed object. Actively obtain relevant data, which forms the observer to actively "pull data" from the observed object. The static class diagram is as follows: