设计模式二:观察者模式(java内置)

把对象变成观察者:实现观察者接口(java.util.Observer),然后调用Observable对象的addObserver()方法或deleteObserver()

可观察者送出通知:

1、扩展java.util.Observable类产生"可观察者"类

2 、1)先调用Observable的setChanged()方法,标记主题的状态已经改变,让notifyObservers()知道当它被调用时应该更新观察者,如果调用notifyObservers()之前没有调用setChanged(),观察者就不会被通知更新。

Observable的setChanged()方法(修饰符是protected,不能创建Observable实例并组合到自己的对象中因为不能使用setChanged()方法,除非继承Observable类):

 protected synchronized void setChanged() {
        changed = true;
    }

      2)调用两种notifyobservers()方法中的一个:

notifyobservers()或notifyobservers(Object arg)

java.util.Observable的notifyobservers(Object arg)的方法:

Object arg:当通知时,可以把arg(数据对象data object)通过update方法传送给每一个观察者

 public void notifyObservers(Object arg) {
        Object[] arrLocal;
        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

java.util.Observable的notifyobservers()方法:

 public void notifyObservers() {
        notifyObservers(null);
    }

观察者如何接收通知:

观察者实现了跟新的方法:

update(Observable o,Object arg)

Observable o:主题本身当作第一个变量,好让观察者知道是哪个主题通知它的

Object arg:是传入notifyobservers()的数据对象,如果没有则说明为空。

如果想"推"(push)数据给观察者,可以把数据当作数据对象传送给notifyobservers()方法。否则,观察者必须从可观察者对象中"拉"(pull)数据。

下面通过观察者从可观察者处拉数据的演示:

1、把WeatherData改成使用java.util.Observable

package com.ya;

import java.util.ArrayList;
import java.util.Observable;

public class WeatherData extends Observable{
    private float temperature;
    private float humidity;
    private float pressure;
    
    public WeatherData(){    }
    
    public void measurementsChanged(){
        //调用notifyObservers()方法之前先调用setChanged()
    	setChanged();
        //如果该方法的参数没有Object数据对象,这表示采用的是观察者主动向可观察者"拉"的方式
    	notifyObservers();
    }
    public void setMeasurements(float temperature,float humidity,float pressure){
    	this.temperature = temperature;
    	this.humidity = humidity;
    	this.pressure = pressure;
    	measurementsChanged();
    }
  //下面三个方法,因为我们要使用"拉"的做法,观察者会利用这些方法获得WeatherData对象的状态
    public float getTemperature(){
    	return temperature;
    }
    
    public float getHumidity(){
    	return humidity;
    }
    
    public float getPressure(){
    	return pressure;
    }
    
}

CurrentConditionsDisplay布告板:

package com.ya;

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

public class CurrentConditionsDisplay implements Observer,DisplayElement{
	Observable observable;
	private float temperature;
	private float humidity;
	private float pressure;
	public CurrentConditionsDisplay(Observable observable) {
		this.observable = observable;
		observable.addObserver(this);
	}
	
	@Override
	public void update(Observable obs, Object obj) {
		if(obs instanceof WeatherData){
			WeatherData weatherData = (WeatherData)obs;
			this.temperature = weatherData.getTemperature();
			this.humidity = weatherData.getHumidity();
			display();
		}
		display();
	}
	
	public void display(){
		System.out.println("Current conditions:" + temperature + "F degrees and"+ humidity +" %humidity");
	}

}

测试代码类WeatherStation:

package com.ya;

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

有多个公布板时(观察者),测试结果每次输出的次序不一样,而自定义观察者的模式输出次序每次输出都一样。

这是因为java.util.Observable实现了notifyObservers()方法,调用观察者的update的次序与自定义的观察者模式不一样。

//java内置的可观察者调用观察者的update的次序是后加入的先调用
for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
//自定义的观察者模式调用观察者的update的次序是先加入的先调用
for(int i=0;i<observers.size();i++){
  Observer observer = (Observer)observers.get(i);
  observer.update(temperature,humidity,pressure);
}

在JDK中,不是只有java.util中才能找到观察者模式,在JavaBeans和Swing中,也都实现了观察者模式。

转载于:https://my.oschina.net/u/3723612/blog/1613991

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值