本文目录
1. 这篇博客的由来
观察者模式是Head First 设计模式中的第二种设计模式,书中以气象观测为案例贯穿观察者模式。下面我们来熟悉一下观察者模式吧。
2. 观察者模式介绍
-
观察者模式的定义
定义对象间的一种一对多 的依赖关 系,让多个观察者同时监听某一个主题现象,当一个对象的状态发生改变时,会通知所有观察者对象,所有依赖于它的对象都得到通知并被自动更新。
-
UML图
-
观察者模式的基本角色
- Subject接口(被观察者接口)(确定被观察者对象的基本行为,注册观察者、移除观察者、通知消息) - ConcreteSubject类(被观察者实现类) - Observer(观察者接口)(更新行为) - ConcreteObserver(被观察者实现类)
3. 从气象观测分析观察者模式
- 需求描述
- 分析实现
从上图可以知道,我们事先了解气象站将会给我们什么参数,每当气象站的参数发生改变时,我们的显示装置也要对应发生改变,我们可以拥有多个显示装置(公告板),但每个显示装置的具体显示可能不同。
下面是总体实现图
从上面可以看到,被观察者必须拥有三个方法(加入观察者,移除观察者,通知观察者),被观察者拥有更新数据的方法,因为这里的展示可能不同,所以抽离了一个接口专门做展示功能。
4. 分析气象观测案例的角色
Subject接口实现(被观察者接口类)
package subject;
import observer.Observer;
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
WeatherData类(被观察者实现类)
package subject.impl;
import java.util.ArrayList;
import observer.Observer;
import subject.Subject;
/**
* @author wuliz
* 主题类
*/
public class WeatherData implements Subject {
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
/**
* 初始化容器
*/
public WeatherData(){
observers = new ArrayList();
}
/* (non-Javadoc)
* @see subject.Subject#notifyObserver()
*/
@Override
public void notifyObserver() {
// TODO Auto-generated method stub
for(int i=0;i<observers.size();i++){
Observer o = (Observer)observers.get(i);
o.update(temperature, humidity, pressure);
}
}
@Override
public void registerObserver(Observer o) {
// TODO Auto-generated method stub
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
// TODO Auto-generated method stub
int i = observers.indexOf(o);
if(i>=0){
observers.remove(i);
}
}
/**
* @param temp
* @param humidity
* @param pressure
*/
public void setMeasurements(float temp,float humidity,float pressure){
this.temperature=temp;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public void measurementsChanged(){
notifyObserver();
}
}
Observer接口(观察者接口)
package observer;
public interface Observer {
public void update(float temp,float humidity,float pressure);
}
ConcreteObserver类(观察者实现类)
package observer.impl;
import observer.Observer;
import show.DisplayElement;
import subject.Subject;
public class CurrentConditionDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionDisplay(Subject weatherData){
this.weatherData=weatherData;
this.weatherData.registerObserver(this);
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("温度 :"+temperature+",湿度:"+humidity);
}
@Override
public void update(float temp, float humidity, float pressure) {
// TODO Auto-generated method stub
this.temperature = temp;
this.humidity = humidity;
display();
}
}
5.对比java实现的观察者模式
除我们自己实现的观察者模式,还可以了解一下java jdk 自带实现的观察者模式。
java.util.Observable类(这是一个类,不是接口,需要子类继承超类)
这样做的优点是,我们不再需要实现三个必要的方法。因为这三个方法通常是一样的,但缺点是,通过继承不易扩展。
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;
public Observable() {
obs = new Vector<>();
}
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
public void notifyObservers() {
notifyObservers(null);
}
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);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
java.util.Observer接口
package java.util;
public interface Observer {
void update(Observable o, Object arg);
}