出版社+订阅者=观察者模式
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
我们来看一下观察者模式的类图:
其中的依赖是如何产生的:因为主题是真正拥有数据的人,观察者是主题的依赖者,在数据变化的时候更新,这样比起让许多对象控制同一份数据来,可以得到更干净的oo设计。
松耦合的威力
当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。
观察者模式提供了一种对象设计,让主题和观察者之间松耦合。
关于观察者的一切,主题只知道观察者实现了某个接口(也就是Observer接口)。主题不需要知道观察者的具体类是谁,做了些什么或其他任何细节。
我们可以独立地服用主题或观察者。如果我们在其他地方需要使用主题或观察者,可以轻易地复用,因为二者并非紧耦合。只要他们之间的接口仍被遵守,我们就可以自由的改变他们。
设计原则,为了交互对象之间的松耦合设计而努力。
我们来看看气象台实现的类图
我们目前实现的观察者模式只有主体的push机制,不能由观察者自由的去拉自己想要的数据。java的api有内置的观察者模式。两种方式都是实现了。也就是java.util包内包含的最基本的Observer接口与Observable类。
如何把对象变成观察者
实现观察者接口(java.util.Observer),然后调用任何Observable对象的addObserver()方法,退出观察者时调用deleteObserver()方法即可。
被观察者如何送出通知
1,先调用setchanged()方法,标记状态已经改变的事实。setchanged可以通过其中的标示来控制下数据刷新的灵敏度。
2,然后调用两种notifyObservers()方法中的一个,分别是notifyObservers()和notifyObservers(Object arg)。
观察者如何接收通知
更新方法update(Observable o, Object arg);
新的实现的代码
public class WeatherData extends Observable {//直接继承了Java提供的主题超类,注意这里Observable是一个类
private float temperature;
private float humidity;
private float pressure;
public WeatherData() { }//由于采用内置的主题,这里就不需要你手动维护一个观察者列表了。
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;
}
}
我们现在再创建一个使用Java内置观察者模式完成的气象发布版:
public class CurrentConditionsDisplay implements Observer , DisplayElement {//注意这里Observer是一个接口
Observable observable;//主题的引用,用于注册、注销等操作
private float temperature;
private float humidity;
public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);//这里进行了注册,也可以使用
}
public void update(Observable obs, Object arg) {
if (obs instanceof WeatherData) {//判断是不是属于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");
}
}
java.util.Observable的黑暗面
1,Observable是一个类。不能双继承。
2,Observable将关键方法包含起来了。
setChanged()方法是protected。除非你继承于Observable,否则你无法创建Observale实例并组合到你自己的对象中来。这个设计违反了“多用组合,少用继承”。
一个新的模式,以松耦合方式在一系列对象之间沟通状态。观察者模式的代表人物---MVC。
要点:
1,观察者模式定义了对象之间一对多的关系。
2,主题(也就是可观察者)用一个共同的接口来更新可观察者。
3,观察者和可观察者之间通过松耦合方式结合。
4,使用此模式时,你可以从被观察者处推(push)或者拉(pull)数据(然而,推的方式被认为更“正确”)。
5,有多个观察者时,不可以依赖特定的通知次序。
6,Java有多种观察者模式的实现,包括了通用的java.util.Observable。
7,要注意java.util.Observable实现上所带来的一些问题。