Observer Pattern 观察模式:
关于观察者模式,该书讲的例子是气象观测应用程序,当气象观测站得到新的气象数据时就将数据发送给应用程序,应用程序的模块就会得到相应的数据,这其实也是观察者模式的模型。观察者模式定义了一个一对多的应用模式,一是主题(Subject),也就是气象观测站,多是观察者(Observer),也就是应用程序模块(如:应用程序中有好几个功能,当前天气的展示、最近一周天气的趋势、未来几天的天气预报);当subject数据发生变化时,observer会接收到subject发出的通知。书中还提到一个有助于理解的例子,我们每个人(观察者)都订了报社(被观察者)的杂志,只要报刊有新报纸出版,就会给你送来,只要你是他们的订户,你就会一直受到新报纸。
也就是:出版者+订阅者=观察者模式
这一章就描述了一个设计原则:为了交互对象之间的松藕合设计而努力。我觉得这也是我们用面向对象的设计语言设计程序是所要努力的方向。
下面实现书中的气象观测应用程序:
抽象主题角色:
public interface Subject{
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
抽象观察者角色:
public interface Observer{
public void updata(float temp,float humidity,float pressure);//当主题发生变化时,会将这三者的变化值告诉观察者
public void display();//输出
}
具体主题角色,继承自subject接口
public WeatherData implements Subject{
private ArrayList<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){
observers=new ArrayList<Observer>();
}
public void registerObserver(Observer o){
observers.add(o);
}
public void removeObserver(Observer o){
int i=observers.indexOf(o);
if(i>=0){
observers.remove(i);
}
}
private void notifyObserver(){
for(int i=0;i<observers.size();i++){
Observer observer=observers.get(i);
observer.updata(temperature,humidity,pressure);
}
}
private void measurementsChanged(){//当消息有更新时就发送数据给所有观察者
notifyObserver();
}
//获得气象数据的来源
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChanged();
}
}
具体观察者角色,继承自Observer接口,该类实现了当前天气展示模块,还有其他两个模块与此相似
public class CurrentconditionsDisplay implements Observer{
private Subject weatherData;
private float temperature;
private float humidity;
private float pressure;
public CurrentconditionsDisplay(Subject weatherData){
this.weatherData=weatherData;
weatherData.registerObserver(this);
}
public void updata(float temperature,float humidity,float pressure){
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
display();
}
private void display(){
System.out.println("Temperature:"+temperature+"Humidity:"+humidity+"Pressure:"+pressure);
}
}
客户端类,主应用程序:
public class WeatherStation{
public static void main(String[] args){
WeatherData weather=new WeatherData();
CurrentconditionsDisplay currentconditionsDisplay=new CurrentconditionsDisplay(weatherData);
weather.setMeasurements(23.2,65,30.4f);
weather.setMeasurements(24.3,70,43.1f);
}
}
关于观察者的一切,主题只知道观察者实现了Observer接口,主题不知道观察者具体类是谁,做了些什么或其他任何细节。我们可以在任何时候添加或者删除一个观察者。
其实JavaAPI有内置的观察者模式。java.util包(package)内包含最基本的Observer接口与Observable类,这和我们的Subject接口与Observer接口很相似。有空该看看源代码的实现了。而且在javabeans和swing中也实现了观察者模式。swing的观察者模式就是消息监听机制。无论在java中还是在android中都是这种模式,在android中,当你单击一个按钮时就会触发OnClickListener,此时button就是被观察者,而OnClickListener就是观察者。