Head first design mode-Observer Pattern 2

Source: Internet
Author: User

The observer mode is introduced in the previous blog and the code of the "push" method is implemented. However, there are few introductions about the "pull" mode, the pull mode described in many materials on the Internet is not the observer mode at all. Let's take a look at how the PULL mode is implemented in JDK through some analysis.

This book introduces the built-in observer mode in Java:

Import Java. util. observable; import Java. util. observer; public class weatherdata extends observable {private float temperature; private float humidity; private Float Pressure; // here we do not need to track the observer, you do not need to manage registration and deletion (so that super-class workers can do it ). // Delete the registration, addition, and notification code. Public weatherdata () {// Our constructor no longer needs to create a data structure to remember the observer.} public void measurementschanged () {setchanged (); notifyobservers ();} public void setmeasurements (float temperature, float humidity, Float Pressure) {This. temperature = temperature; this. humidity = humidity; this. pressure = pressure; measurementschanged ();} public float gettemperature () {return temperature;} public float gethumidity () {return humidity;} public float getpressure () {return pressure ;}}

import java.util.Observable;import java.util.Observer;public class CurrentConditionsDisplay implements Observer{Observable observable;private float temperature;private float humidity;public CurrentConditionsDisplay(Observable observable){this.observable = observable;observable.addObserver(this);}@Overridepublic void update(Observable obs, Object arg) {// TODO Auto-generated method stubif(obs instanceof WeatherData){WeatherData weatherData = (WeatherData) obs;this.temperature = weatherData.getTemperature();this.humidity = weatherData.getHumidity();display();}}public void display(){System.out.println("Current conditions:" + temperature + "F degrees and " + humidity + "% humidity");}}

public class Test {public static void main(String[] arg){WeatherData weatherData = new WeatherData();CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);weatherData.setMeasurements(80, 65, 30.4f);weatherData.setMeasurements(82,70,29.2f);}}

The result is the same as before.

At the beginning, I didn't fully understand it here:

If the content of the subject changes, it changes the flag. The observer pulls data from the subject. One thing you cannot understand is: how can the observer immediately know that the subject has changed? I have an implementation of YY on my own. That is, when the subject changes, the observer does not need to be notified, but the observer must be updated. This is like a newspaper paper. Newspapers are updated every day and put in the mailbox. When the poster thinks about it, go to the mailbox and check it. If there is a new newspaper, the message will be sent out. However, this idea is somewhat limited. 1) It is time-sensitive and cannot be updated when changes occur.
2) Each Observer needs a thread to regularly obtain information.

This is different from the observer mode. Some blogs refer to it as another mode, which may have application scenarios.


Later, I asked my colleagues to check the JDK code and find that the internal implementation is similar to the push mode. It also has a structure to maintain the objects to be notified by the subject. However, when the subject calls notifyobserver, it will reference the subject. The observer needs to follow this reference and then take another step to obtain the data needed by the subject.

/* * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.util;/** * This class represents an observable object, or "data" * in the model-view paradigm. It can be subclassed to represent an * object that the application wants to have observed. * <p> * An observable object can have one or more observers. An observer * may be any object that implements interface <tt>Observer</tt>. After an * observable instance changes, an application calling the * <code>Observable</code>'s <code>notifyObservers</code> method * causes all of its observers to be notified of the change by a call * to their <code>update</code> method. * <p> * The order in which notifications will be delivered is unspecified. * The default implementation provided in the Observable class will * notify Observers in the order in which they registered interest, but * subclasses may change this order, use no guaranteed order, deliver * notifications on separate threads, or may guarantee that their * subclass follows this order, as they choose. * <p> * Note that this notification mechanism is has nothing to do with threads * and is completely separate from the <tt>wait</tt> and <tt>notify</tt> * mechanism of class <tt>Object</tt>. * <p> * When an observable object is newly created, its set of observers is * empty. Two observers are considered the same if and only if the * <tt>equals</tt> method returns true for them. * * @author  Chris Warth * @see     java.util.Observable#notifyObservers() * @see     java.util.Observable#notifyObservers(java.lang.Object) * @see     java.util.Observer * @see     java.util.Observer#update(java.util.Observable, java.lang.Object) * @since   JDK1.0 */public class Observable {    private boolean changed = false;    private Vector obs;    /** Construct an Observable with zero Observers. */    public Observable() {        obs = new Vector();    }    /**     * Adds an observer to the set of observers for this object, provided     * that it is not the same as some observer already in the set.     * The order in which notifications will be delivered to multiple     * observers is not specified. See the class comment.     *     * @param   o   an observer to be added.     * @throws NullPointerException   if the parameter o is null.     */    public synchronized void addObserver(Observer o) {        if (o == null)            throw new NullPointerException();        if (!obs.contains(o)) {            obs.addElement(o);        }    }    /**     * Deletes an observer from the set of observers of this object.     * Passing <CODE>null</CODE> to this method will have no effect.     * @param   o   the observer to be deleted.     */    public synchronized void deleteObserver(Observer o) {        obs.removeElement(o);    }    /**     * If this object has changed, as indicated by the     * <code>hasChanged</code> method, then notify all of its observers     * and then call the <code>clearChanged</code> method to     * indicate that this object has no longer changed.     * <p>     * Each observer has its <code>update</code> method called with two     * arguments: this observable object and <code>null</code>. In other     * words, this method is equivalent to:     * <blockquote><tt>     * notifyObservers(null)</tt></blockquote>     *     * @see     java.util.Observable#clearChanged()     * @see     java.util.Observable#hasChanged()     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)     */    public void notifyObservers() {        notifyObservers(null);    }    /**     * If this object has changed, as indicated by the     * <code>hasChanged</code> method, then notify all of its observers     * and then call the <code>clearChanged</code> method to indicate     * that this object has no longer changed.     * <p>     * Each observer has its <code>update</code> method called with two     * arguments: this observable object and the <code>arg</code> argument.     *     * @param   arg   any object.     * @see     java.util.Observable#clearChanged()     * @see     java.util.Observable#hasChanged()     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)     */    public void notifyObservers(Object arg) {        /*         * a temporary array buffer, used as a snapshot of the state of         * current Observers.         */        Object[] arrLocal;        synchronized (this) {            /* We don't want the Observer doing callbacks into             * arbitrary code while holding its own Monitor.             * The code where we extract each Observable from             * the Vector and store the state of the Observer             * needs synchronization, but notifying observers             * does not (should not).  The worst result of any             * potential race-condition here is that:             * 1) a newly-added Observer will miss a             *   notification in progress             * 2) a recently unregistered Observer will be             *   wrongly notified when it doesn't care             */            if (!changed)                return;            arrLocal = obs.toArray();            clearChanged();        }        for (int i = arrLocal.length-1; i>=0; i--)            ((Observer)arrLocal[i]).update(this, arg);    }    /**     * Clears the observer list so that this object no longer has any observers.     */    public synchronized void deleteObservers() {        obs.removeAllElements();    }    /**     * Marks this <tt>Observable</tt> object as having been changed; the     * <tt>hasChanged</tt> method will now return <tt>true</tt>.     */    protected synchronized void setChanged() {        changed = true;    }    /**     * Indicates that this object has no longer changed, or that it has     * already notified all of its observers of its most recent change,     * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.     * This method is called automatically by the     * <code>notifyObservers</code> methods.     *     * @see     java.util.Observable#notifyObservers()     * @see     java.util.Observable#notifyObservers(java.lang.Object)     */    protected synchronized void clearChanged() {        changed = false;    }    /**     * Tests if this object has changed.     *     * @return  <code>true</code> if and only if the <code>setChanged</code>     *          method has been called more recently than the     *          <code>clearChanged</code> method on this object;     *          <code>false</code> otherwise.     * @see     java.util.Observable#clearChanged()     * @see     java.util.Observable#setChanged()     */    public synchronized boolean hasChanged() {        return changed;    }    /**     * Returns the number of observers of this <tt>Observable</tt> object.     *     * @return  the number of observers of this object.     */    public synchronized int countObservers() {        return obs.size();    }}

/* * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.util;/** * A class can implement the <code>Observer</code> interface when it * wants to be informed of changes in observable objects. * * @author  Chris Warth * @see     java.util.Observable * @since   JDK1.0 */public interface Observer {    /**     * This method is called whenever the observed object is changed. An     * application calls an <tt>Observable</tt> object's     * <code>notifyObservers</code> method to have all the object's     * observers notified of the change.     *     * @param   o     the observable object.     * @param   arg   an argument passed to the <code>notifyObservers</code>     *                 method.     */    void update(Observable o, Object arg);}

The "push" method means that the subject maintains a list of observers. Whenever an update occurs, the subject actively pushes the UPDATE message to each observer. The "pull" method means to notify the observer when the subject changes, and then the observer decides to use the appropriate method to obtain the corresponding update data from the subject.


The benefits of "pushing" include:

1. Efficient. If no update occurs, there will be no message update push actions, that is, each message push occurs after a real update event, which makes sense.

2. Real-time. The notification operation can be triggered immediately after an event occurs.

3. You can set the notification time by subject to avoid busy hours.

4. The sequence of events can be expressed.

Benefits of "pull" include:

1. The observer can ignore the change events it does not care about. You only need to obtain the events you are interested in.

2. The observer can determine the time and method for obtaining the update event.

3. the PULL mode allows the subject to better control the access permissions of each observer to query and update each time, because the observer uses the getter method of the subject to obtain data.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.