一、什么情况下考虑使用“观察者设计模式”?
观察者设计模式定义了对象之间的一对多的依赖关系,当主题对象改变状态时,它的所有观察者都会收到通知并且自动更新。
来具体分析一下下面的一个应用场景:
WeatherData为一个气象站提供的气象信息的实体类,当WeatherData中的信息发生变化时,需要让两个显示面板(CurrentConditionsDisplay和AnotherCondisDisplay)中相应的信息发生改变。这里我们就可以使用观察者设计模式。
观察者模式中的两个概念:
①主题(subject),一对多关系中的“一”端,也可以称为可观察对象。这里为WeatherData
②观察者(observer),一对多关系中的“多”端。这里为各种Display。
我们所要实现的功能就是当主题中的信息发生改变时可以通知所有的观察者,并让观察者做出相应的反应。
二、如何实现观察者模式?
①首先主题作为“一”端能够通知观察者的“多”端,所以主题中应当具有可以新增、删除观察者和通知观察者方法,所以就可以定义一个主题接口Subject如下:
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
②观察者作为“多”端,虽然各不相同,但是必须遵循一定的规则,主题才能使用面向接口的编程方法,来实现统一的调用,所以我们为观察定义了统一的改变数据的方法update(),如下:
public interface Observer {
void update(double temperature, double humidity, double pressure);
}
观察者如果需要遵循统一的展示接口,这里可以根据实际需要,自己来进行定义,我们定义了DisplayElement接口
public interface DisplayElement {
public void display();
}
③在定义了上面的接口之后,主题中需要存储所有观察者的列表信息,并且能够根据观察者,进行自动的新建或者删除,所以我们可以在观察者的构造方法中调用主题的新增观察者方法,实现观察的新增如下:
public class CurrentConditionsDisplay implements Observer, DisplayElement{
private double temperature;
private double humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData){
this.weatherData=weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("temperature: " + temperature);
System.out.println("humidity:" + humidity);
}
@Override
public void update(double temperature, double humidity, double pressure) {
this.temperature=temperature;
this.humidity=humidity;
display();
}
}
然后当主题的数据发生改变时可以循环调用观察者中的update()方法,实现联动。
java中也有内置的观察者模式,分别为:java.util.Observer和java.util.Observerable,只是Observer为接口,Observerable为主题的实现类,使用起来也比较的方便。