One, the Observer pattern definition:
Defines a one-to-many dependency between objects, so that when an object changes state, all of his dependents are notified and updated automatically.
The Observer provides an object design that allows for a loose coupling between the subject and the observer.
Second, the components:
1. Abstract target Role (Subject): Also known as the subject, the target role knows his observer, can have any number of observers to observe the same target, and provides an interface to register and delete the Observer object. The target role is often implemented by an abstract class or interface.
2. Abstract observer Role (Observer): Also known as the Observer, defines an update interface for objects that need to be notified when the target changes. Abstract observer roles are primarily implemented by abstract classes or interfaces.
3, the specific target role (concrete Subject): Also known as the implementation of the theme, will be related to the status of concrete observer objects. When his state changed, he gave notice to his various observers.
4, the specific observer role (concrete Observer): Also known as the implementation of the observer, storage related state, these States should be consistent with the status of the target. Implements the observer update interface to keep its state consistent. You can also maintain a reference to the concrete subject object within this role.
Three, design principles (only part of the design principles, all design patterns are common):
1, in order to interact with the design of loose coupling between objects to work. The loosely coupled design allows us to build resilient OO systems that can cope with change because the interdependence between objects is minimized.
2. Find out what is going to change in the program, and then separate it from the invariant aspects (in the observer pattern, it changes the state of the subject and the number and type of the observer.) With this pattern, you can change the subject-dependent object without changing the theme, call ahead planning! )
3, for the interface programming, not for the implementation of programming. (both the subject and the observer use interfaces, and the viewer uses the interface of the topic to register the subject, and the subject uses the Observer interface to notify the Observer, which allows the two to function properly while having the advantage of loose coupling)
4, multi-use combination, less with inheritance (Observer patterns use "combination" to combine many observers into the subject.) This relationship between objects is not generated by inheritance, but by the way they are combined at run time.
Four, the application scenario:
1, when an object changes to other objects, and he does not know how many objects to be changed, you can use the Observer pattern.
2, an abstract model has two aspects, when one aspect depends on another aspect, then the observer pattern can be encapsulated in separate objects so that they independently change and reuse.
V. Advantages and Disadvantages:
Advantages:
The observer pattern relieves the coupling between the subject and the specific observer, allowing both sides of the coupling to rely on abstraction, rather than relying on specifics, so that their changes do not affect the change on the other side.
Disadvantages:
The dependency is not completely lifted, and the abstract notifier still relies on the abstract observer.
Six, the specific demo
Demand:
Need three plates to show the weather conditions, respectively: the current situation plate, meteorological statistics section, Weather forecast plate.
The current situation plate needs to display "temperature, humidity, pressure". This data needs to be obtained from a weather station,
and need to get in time, as long as the weather station update data, the three plates will be synchronized display.
Scenario 1: We implement the Observer pattern ourselves without borrowing any APIs:
1, first define a topic (Subject) interface, there is no doubt that there is a need to register the Observer, the method of removing the observer,
There is also a way to push messages to the observer.
2, also need an observer (Observer) interface, there is only one update of the method of updating data
3, the last one is the plate (displayelement) interface, there is only one method, display, is responsible for displaying the data method
4, Next is the need to write an implementation class responsible for implementing the theme interface, and three plate classes are responsible for implementing the Observer interface and plate interface.
and the implementation class of the three plates also requires a pointer to a topic to point to the object of the theme implementation class.
package observer;/** * Description: Theme interface * @author Chentongwei * @date May 24, 2016 PM 12:46:52 * @version 1.0 */public Interface Subject {// Register Observer method void Registerobserver (Observer o);//unregister observer method void Removeobserver (Observer o);//method that is responsible for pushing data to the observer void Notifyobservers ();}
Package Observer;import java.util.arraylist;/** * Description: Theme Implementation class * @author Chentongwei * @date May 24, 2016 afternoon 12:51:18 * @versi On 1.0 */public class Weatherdata implements Subject {//Viewer collection private arraylist<observer> observers;//temp Private Float temperature;//Humidity Private float humidity;//air pressure private float pressure;public weatherdata () {observers = new arraylist& Lt;observer> ();} Registered observer @overridepublic void Registerobserver (Observer o) {if (null! = O) {observers.add (o);}} Remove observer @overridepublic void Removeobserver (Observer o) {if (null! = o && observers.indexof (o) >= 0) {observers. Remove (Observers.indexof (o));}} Responsible for pushing messages to observers @overridepublic void Notifyobservers () {for (int i = 0; i < observers.size (); i + +) {Observer Observer = Obs Ervers.get (i); observer.update (temperature, humidity, pressure);}} We notify the Observer public void measurementschanged () {notifyobservers () when the observed value is updated from the weather station to;} public void setmeasurements (float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = Humidity;this.pressure = Pressure;measurementschanged ();}}
Package observer;/** * Description: Observer interface, all meteorological components implemented this viewer interface * @author Chentongwei * @date May 24, 2016 PM 12:48:55 * @version 1.0 * /public interface Observer {//is responsible for updating data void update (float temp, float humidity, float pressure);}
Package observer;/** * Description: Common interface of the plate * @author Chentongwei * @date May 24, 2016 PM 12:49:39 * @version 1.0 */public Interfa Ce displayelement {//method for displaying data void display ();}
Package observer;/** * Description: Viewer Implementation class * @author Chentongwei * @date May 24, 2016 PM 1:06:16 * @version 1.0 */public Class Curre Ntconditionsdisplay implements Observer, displayelement {//Temp private float temperature;//humidity private float humidity;// Subject Private Subject weatherdata;public Currentconditionsdisplay (Subject weatherdata) {this.weatherdata = Weatherdata; Weatherdata.registerobserver (this);} Responsible for displaying data @overridepublic void display () {System.out.println ("Current conditions:" + temperature + "F degress and" + humid ity + "% humidity");} Responsible for updating data @overridepublic void update (float temp, float humidity, float pressure) {this.temperature = Temp;this.humidity = h Umidity;display ();} public static void Main (string[] args) {Weatherdata weatherdata = new Weatherdata (); Currentconditionsdisplay conditionsdisplay = new Currentconditionsdisplay (weatherdata); weatherData.setMeasurements (30.4f); Weatherdata.setmeasurements (weatherdata.setmeasurements, 29.2f); (+, +, 30.4f);}}
Scenario 2: We take advantage of the Java built-in observer pattern:
The Java API has a built-in observer pattern, and the Java.util package contains the most basic observer interfaces and observable classes.
This is similar to our custom subject interface with the Observer interface.
1, we do not need to define a topic interface, we only need to declare a class to inherit the observable class under the Java.util package.
2, we do not need to define an observer interface, we only need to declare a class to implement the Observer interface under Java.util
3, plate interface with the scheme 1
Answer questions for Scenario 2:
(a) How to turn an object into an observer?
As before, implement the Observer Interface (Java.util.Observer), and then call the Addobserver () method of any observable object. Don't want to be
Observer, call the Deleteobserver () method directly.
(ii) How can the viewer (subject) Send notice?
First, you need to use the extended Java.util.Observable interface to generate the "observable" class, and then you need the following two steps
① first calls the Setchange () method to mark the fact that the state has changed.
Description: The Setchange () method is used to mark the fact that the state has changed so that notifyobservers () knows that the observer should be updated when he is called, if Notifyobservers () is called before
Without first calling Setchange (), the observer will not be notified. The following is the internal source code for observable:
Setchange () {changed = TRUE;} Notifyobservers (Object Arg) {if (changed) {for every observer on the list {call Update (this, arg);} changed = FALSE;}} Notifyobservers () {notifyobservers (null);}
② then calls one of the two Notifyobservers () methods:
Notifyobservers ()
Or
Notifyobservers (Object arg)//When notified, this version can transmit any data object to each observer
(iii) How do observers receive notifications?
As with previous methods, the observer implements the updated method, but the signature of the method is not the same:
/**
* O: The theme itself as the first variable so that the observer knows which subject informs him
* arg: for arg above notifyobservers (Objectarg)
* arg If NULL, no data is indicated
*
* If you want to "push" the data to the observer, you can transfer the number as a data object to the Notifyobservers (arg) method, otherwise
* The Observer must "pull" the data from the observable object
*/
Update (Observable o, Object arg)
The specific demo is as follows:
package Observer;import java.util.observable;/** * Description: Theme Implementation class * @author Chentongwei * @date May 24, 2016 afternoon 4:06:46 * @version 1.0 * /public class WeatherData2 extends Observable {//Temp private float temperature;//humidity private float humidity;//air pressure private Float Pressure;public WeatherData2 () {//Our constructors no longer need to build data structures in order to remember the observers}public void measurementschanged () {// Before calling Notifyobservers (), call setchanged () to indicate that the state has changed setchanged ();//Note: We did not call Notifyobs () to transfer the data object, which means we are using "pull" Notifyobservers ();} public void setmeasurements (float temperature, float humidity, float pressure) {this.temperature = temperature; this.humidity = Humidity;this.pressure = Pressure;measurementschanged ();} Because we are taking the "pull" approach, we must provide these methods of obtaining data. public float gettemperature () {return temperature;} public float gethumidity () {return humidity;} public float getpressure () {return pressure;}}
Package Observer;import Java.util.observable;import Java.util.observer;public class CurrentConditionsDisplay2 Implements Observer, displayelement {Observable observable;private float temperature;private float humidity;public CurrentConditionsDisplay2 (Observable Observable) {this.observable = Observable;observable.addobserver (this);} @Overridepublic void Display () {System.out.println ("Current conditions:" + temperature + "F degress and" + humidity + "% Humidity ");} @Overridepublic void Update (Observable o, Object Arg) {if (o instanceof WeatherData2) {WeatherData2 weatherData2 = new Weat HerData2 (); this.temperature = Weatherdata2.gettemperature (); this.humidity = Weatherdata2.gethumidity ();d isplay ();}} public static void Main (string[] args) {WeatherData2 weatherData2 = new WeatherData2 (); CurrentConditionsDisplay2 conditionsDisplay2 = new CurrentConditionsDisplay2 (WEATHERDATA2); Weatherdata2.setmeasurements (30.4f), weatherdata2.setmeasurements (--------); Weatherdata2.setmeasurements(30.4f);}}
Attention:
The dark side of the java.util.Observable:
1, the observable is a "class" rather than an "interface", and worse, he did not even implement an interface, unfortunately, the implementation of java.util.Observable has many problems, limiting his use and reuse.
2, observable is a class, you have to design a class to inherit him, if some class want to have observable class and another superclass behavior, it will fall into a dilemma, after all, Java does not support multiple inheritance, which limits the potential of observable reuse
3, see Observableapi can find Setchanged () method is protected (defined as protected), means: Unless you inherit from observable, otherwise you cannot create observable instances and combine into your own objects, This violates the design principle: "Multi-use combination, less inheritance".
Vii. Summary of key points:
1. The Observer pattern defines a one-to-many relationship between objects.
2. The subject (i.e., the observer also called the abstract target role) uses a common interface to update the observer.
3, the Observer and the observer in a loosely coupled way, the observer does not know the details of the observer, only that the Observer realizes the Observer interface.
4. When using this mode, you can "push" or "pull" data from the Observer (the way you feel "pushed" more "correctly")
5. When there are multiple observers, you cannot rely on a specific notification order.
6, Java has many of the implementation of the observer pattern, including the general java.util.Observable
7, pay attention to some problems brought about by the realization of java.util.Observable
8, if necessary, can realize their own observable, it is not difficult, do not be afraid.
9. SWING uses observer patterns extensively, as are many GUI frameworks.
10, this mode is also used in many places, such as: JavaBeans, RMI and so on.
Second, observer mode--Xiao Wei take you to learn design patterns