观察者模式
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新;
从上述描述中,我们可知观察者模式主旨是一对多的关系,多个隔离性的对象依赖与一个独特对象,需要获取该对象实时状态;
这个情景如同订阅报纸行为:
- 报社的业务就是出版报纸;(独特功能对象)
- 向报社订阅报纸,有新报纸出版,就会向你送来报纸,只要你是他们的订户;
- 当取消订阅时,它们将停止给你派送报纸;
- 只要报社运营着,就会有人向他们订阅或者取消订阅;
从上述类图中,可以看出观察者模式最关键实现部分是两个接口的使用;
举个栗子:
主题接口,也可称为可观察者接口
Observerable
public interface Observerable {
//注册观察者资格
public void registerObserver(Observer observer);
//取消观察者资格
public void removeObserver(Observer observer);
//可观察者状态通知
public void notifyObserver();
}
观察者接口
Observer
public interface Observer {
public void update(float temperature, float humidity, float pressure);
}
可观察者对象实现
WeatherData
public class WeatherData implements Observerable {
private float temperature;
private float humidity;
private float pressure;
private ArrayList<Observer> observers;//观察者队列
public WeatherData() {
observers = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
int i = observers.indexOf(observer);
if(i > 0)
{
observers.remove(i);
}
}
@Override
public void notifyObserver() {
for (Observer o : observers) {
o.update(this.temperature, this.humidity, this.pressure);
}
}
public void measurementsChange()
{
notifyObserver();
}
public void setMeasurements(float temperature, float humidity, float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChange();
}
}
观察者对象
CurrentConditionDisplay
public class CurrentConditionDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Observerable weatherData;
public CurrentConditionDisplay(Observerable weatherData) {
this.weatherData = weatherData;
this.weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("Current condition:" + this.temperature + "F degrees and " + this.humidity + "% humidity.");
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
}
通过上述的解耦,当观察者对象任意增加时我们只需要调用可观察者对象registerObserver()
进行注册即可得到可观察者对象的变化,同样也可以依据自身需要进行取消观察;
对于观察者模式的实现,JDK已经提供比较完善的支持:
可观察者对象:
Observable
public class Observable {
private boolean changed = false;
private Vector 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();
}
}
观察者对象:
public interface Observer {
void update(Observable o, Object arg);
}
通过上面JDK源码查阅,基本所实现的功能都是一模一样的,Observable对象更是提供线程安全的保证,只是采用继承的实现方法给我们自身进行应用带来一点麻烦;