Java内置观察者模式的运行机制

源码分析

Java内置观察者模式使用了一个类 Observable,一个接口 Observer

分析类 Observable

private boolean changed = false;
    private Vector<Observer> obs;

    /** Construct an Observable with zero Observers. */

    public Observable() {
        obs = new Vector<>();
    }

notifyObservers()和notifyObservers(Object)依赖于 changed的状态,判断changed状态来决定观察者是否update,

在更新完成后clearChanged();

 /**
     * 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);
    }
特别注意notifyObserveres(Object)方法
 1、arrLocal数组对象的作用-临时缓存,用于存储Observers的快照

 2、sychronized(this)同步处理会导致两个问题,新加入的Observer对象不会通知,最近的unregistered对象仍会执行通知

实例说明

1、对象如何变成观察者

通过实现Observer接口,然后调用Observable对象的addObserver();

package org.watt.thinkinginjava.observer.java;

import java.util.Observable;
import java.util.Observer;

public class CurrentConditionDisplay implements Observer, DisplayElement {
	private float temperature;
	private float humidity;
	private float pressure;
	private Observable observable;

	public CurrentConditionDisplay(Observable observable) {
		this.observable = observable;
		observable.addObserver(this);
	}

	public void display() {
		System.out.println("CurrentConditionDisplay: " + temperature + " ," + humidity + ", " + pressure);

	}

	public void update(Observable o, Object arg) {
		if (o instanceof WeatherData) {
			WeatherData weatherData = (WeatherData) o;
			this.temperature = weatherData.getTemperature();
			this.humidity = weatherData.getHumidity();
			display();

		}

	}

}

2、可观察者如何送出通知

可观察者继承Observable对象通过设置change状态

package org.watt.thinkinginjava.observer.java;

import java.util.Observable;

public class WeatherData extends Observable {
	private float temperature;
	private float humidity;
	private float pressure;


	public void measurementsChanged() {
		//设置changed标识状态
		setChanged();
		notifyObservers();
	}

	public void setMeasurements(float temperature, float humidity, float pressure) {
		this.setTemperature(temperature);
		this.setHumidity(humidity);
		this.setPressure(pressure);
		measurementsChanged();
	}

	public float getTemperature() {
		return temperature;
	}

	public void setTemperature(float temperature) {
		this.temperature = temperature;
	}

	public float getHumidity() {
		return humidity;
	}

	public void setHumidity(float humidity) {
		this.humidity = humidity;
	}

	public float getPressure() {
		return pressure;
	}

	public void setPressure(float pressure) {
		this.pressure = pressure;
	}
}

3、观察者如何接收通知

观察者实现update方法

public void update(Observable o, Object arg) {
                 //从WeatherData中获取数据
		if (o instanceof WeatherData) {
			WeatherData weatherData = (WeatherData) o;
			this.temperature = weatherData.getTemperature();
			this.humidity = weatherData.getHumidity();
			display();

		}

	}

Observable用来定位是哪个主题通知你的,也可以把数据当作数据对象传给notifyObservers(args),在调用update时传入

public void update(Observable o, Object arg) {
		         //传入对象中获取
                       WeatherData weatherData = (WeatherData) arg;
			this.temperature = weatherData.getTemperature();
			this.humidity = weatherData.getHumidity();
			display();
}

总结

1、内置观察者模式Obserable是个对象,一般情况下是面向接口编程,这个比较特别,而且setChanged等方法是protected,只有继承才能使用控制观察者对象;

2、Observer接口方法的使用,可以通过两种方式来传递数据,一种是继承Obserable生成的对象,另一种是使用update的第二个参数传入。



猜你喜欢

转载自blog.csdn.net/wxb880114/article/details/80556411