观察者模式(Head First版)

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

 有这样一个需求:

一个气象站,它会提供气温,气压,湿度等气象数据,要实现一个显示当前气象状态的显示装置。

能显示当前气温、气压、湿度等。当气象站的数据一发生改变,就能通知显示装置。

使用观察者模式实现。

 

先看看观察者模式类图:

 

主题是一个接口,定义了注册观察者、删除观察者、通知方法

package com.headfirst.chapter2;

public interface Subject {//主题
	public void registerObserver(Observer o);//添加观察者
	public void removeObserver(Observer o);//删除观察者
	public void notifyObserver();//通知观察者
}

 

 

观察者也是一个接口,主题的notifyObserver方法会调用观察者的update方法。

package com.headfirst.chapter2;

public interface Observer {//观察者
	public void update(float temp,float humidity,float pressure);
}

 

根据上面的需求,我们实现具体的主题,代码如下:

package com.headfirst.chapter2;

import java.util.ArrayList;
import java.util.List;

public class WeatherDataSubject implements Subject {
	private float temp;// 温度
	private float humidity;// 温度
	private float pressure;// 气压
	private List observers;// 这个列表用于存入观察者

	public WeatherDataSubject() {
		observers = new ArrayList();
	}

	public void registerObserver(Observer o) {
		observers.add(o);
	}

	public void removeObserver(Observer o) {
		int i = observers.indexOf(o);
		if (i >= 0) {
			observers.remove(i);
		}
	}

	public void notifyObserver() {
		for (int i = 0; i < observers.size(); i++) {
			Observer observer = (Observer) observers.get(i);
			observer.update(temp, humidity, pressure); //依次通知观察者
		}
	}

	public void measurementChanged() {
		notifyObserver();
	}

	public void setMeasurements(float temp, float humidity, float pressure) {
		this.temp = temp;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementChanged();
	}
}

 

 

观察者

package com.headfirst.chapter2;

public class CurrentConditionDisplay implements Observer {
	private float temp;
	private float humidity;
	private float pressure;

	public CurrentConditionDisplay(Subject weatherDataSubject) {
		weatherDataSubject.registerObserver(this);
	}

	public void update(float temp, float humidity, float pressure) {
		this.temp = temp;
		this.humidity = humidity;
		this.pressure = pressure;
		display();
	}

	public void display() {//显示方法 
		System.out.println("temp = "+temp+",humidity = "+humidity+", pressure = "+pressure);
	}

}

 

测试类

package com.headfirst.chapter2;

public class Test {
	public static void main(String[] args) {
		WeatherDataSubject subject = new WeatherDataSubject();
		Observer observer = new CurrentConditionDisplay(subject);
		subject.setMeasurements(32, 11, 420);
	}
}

 

使用JAVA内置的观察者模式

JAVA的util包中提供了内置的观察者模式API,分别是Observable类和Observer接口。

 

它可以使用推或拉的方式传输数据。

其中setChanged()方法用来标识状态是否已经改变的事实,如果调用notifyObservers()方法前没有先调用setChanged方法,那么观察都就不会被通知。

setChanged方法可以在更新观察者时,有更多弹性,可以适当通知观察者,例如气象站很敏锐,每十分之一度就会更新,这会造成显示装置不断被通知。

我们可以通过setChanged方法将通知频度设为一度通知更新一次。

把上面的例子使用内置观察者模式重写一遍:如下

package com.headfirst.chapter2;

import java.util.Observable;
//主题
public class WeatherData extends Observable {
	private float temp;// 温度
	private float humidity;// 温度
	private float pressure;// 气压

	public void measureChanged() {
		setChanged();
		notifyObservers();
	}

	public void setMeasurement(float temp, float humidity, float pressure) {
		this.temp = temp;
		this.humidity = humidity;
		this.pressure = pressure;
		measureChanged();
	}

	public float getTemp() {
		return temp;
	}

	public float getHumidity() {
		return humidity;
	}

	public float getPressure() {
		return pressure;
	}

}

 

package com.headfirst.chapter2;

import java.util.Observable;
import java.util.Observer;
//观察者
public class ConditionDisplay implements Observer {
	private float temp;
	private float humidity;
	private float pressure;
	
	public ConditionDisplay(Observable o) {
		o.addObserver(this);
	}
	
	public void update(Observable arg0, Object arg1) {
		if(arg0 instanceof WeatherData){
			WeatherData data = (WeatherData)arg0;
			this.temp = data.getTemp();
			this.humidity = data.getHumidity();
			this.pressure = data.getPressure();
			display();
		}
	}
	
	public void display(){
		System.out.println("temp = "+temp+",humidity = "+humidity+", pressure = "+pressure);
	}

}

 

测试类:

package com.headfirst.chapter2;

import java.util.Observer;

public class Test {
	public static void main(String[] args) {
		WeatherData data = new WeatherData();
		Observer observer = new ConditionDisplay(data);
		data.setMeasurement(23, 411, 89);
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值