设计模式入门学习之观察者模式(2)
关键字: 设计模式java API提供了内置的观察者模式,java.util包内包含最基本的Observer接口和Observable类,这和我们在上一篇介绍观察者模式中写的Subject接口和Observer很相似,但使用内置的更方便,因为许多功能已经事先准备好了,你甚至可以使用推(push)或拉(pull)的方式传送数据.
那么我们来看一下java内置的观察者模式如何运作:
1.如何把对象变成观察者
如同以前一样,实现观察者接口java.util.Observer,然后调用任何Observable对象的addObserver()方法,删除观察者可以用deleteObserver()方法
2.可观察者要如何送出通知...
a.扩展java.util.Observable接口产生"可观察者"类
b.先调用setChanged()方法,标记状态已经改变的事实,好让notifyObservers()知道当它被调用是应该更新观察者,我们来看下Observer内部,以了解这一 切:
setChanged(){
changed=true; //把change设为true
}
//当通知时,此版本可以传送任何的数据对象给每一个观察者
notifyObservers(Object arg){
//notifyObservers只会在change为true时才会通知观察者
if(change){
for every observer on the list{
call update(this,arg)
}
//通知观察者之后把change标志设为false
change=false;
}
}
notifyObservers(){
notifyObservers(null);
}
//...c.然后调用上面2种notifyObservers()方法中的一个
3.观察者如何接收通知? 一样,观察者实现了更新的方法,但是签名不太一样
/** * 参数1:主题本身,好让观察者知道是哪个主题通知它 * 参数2:传入notifyObservers()的数据对象,没有则为null / update(Observer o,Object org)
如果你想推(push)数据给观察者,你可以把数据当作数据对象传送给notifyObservers(arg)方法
但是如何拉(pull)数据呢,我们来改造气象站:
//---------------把WeatherDate改成使用java.util.Observable
public class WeatherData extends Observable {
//继承Observable,不需要追踪观察者了,也不要管理注册和删除,让超类代劳
private float temperature;
private float humidity;
private float pressure;
public WeatherData() { }
public void measurementsChanged() {
//先调用setChanged来指示状态已经改变
setChanged();
//注意:我们没有传送数据对象,这表示我们采用的做法是"拉(pull)"
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
public class CurrentConditionsDisplay implements Observer, DisplayElement {
Observable observable;
private float temperature;
private float humidity;
//构造器需要observable作为参数,并将CurrentConditionsDisplay对象登记为观察者
public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
//这里也是要改变的地方,先确定观察者属于WeatherData类型,再调用get方法获取温度和湿度并显示
public void update(Observable obs, Object arg) {
if (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");
}
}
如果你运行了这2个例子,你会发现,文字输出的次序不一样,不要依赖于观察者被通知的次序
你可能注意到了,java.util.Observable是一个类而不是一个接口,所以你必须设计一个类继承它,如果一个类想同时具有Observable类和另一个超类的行为,就会陷入两难,比较java不支持多重继承,这限制了Observable的复用能力,仔细看Observable API,setChange()方法是protected,被保护起来了,这就意味着:除非你继承Observable,否则你无法创建Observable示例并组合到你自己的对象中,这个设计违反了第二个设计原则:多用组合,少用继承.
不管你用哪种方法,反正你已经熟悉观察者模式了,不是吗?
评论
改过来了,谢谢!
发表评论
- 浏览: 20858 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
我的相册
共 30 张
最近加入圈子
最新评论
-
使用iBatis的自动化代码生 ...
有没有根据类生产数据库和xml的?
-- by aninfeel -
使用iBatis的自动化代码生 ...
IBatis去除注释版 http://hugh-lin.javaeye.com/ ...
-- by hugh-lin -
使用iBatis的自动化代码生 ...
我的不能用啊,郁闷掉了,真的是很黄很暴力。
-- by horror -
搭建Cloud Computing测试 ...
to fredzhang : 呵呵,我只是说用hadoop/hbase来搭 ...
-- by blank -
搭建Cloud Computing测试 ...
1. gfs的论文你仔细阅读过了吗?它的思想决定了基于它应当如何来实现,如何才能 ...
-- by fredzhang






评论排行榜