观察者模式
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
这个模式很好理解,就是多个观察者类观察一个具体的主题,当这个主题改变时,所有的观察者就都知道了这一改变,当某个观察者不再观察这个主题时,则不会注意到这个改变。例如我们生活中的订阅或关注,当你订阅了某个杂志或者关注了某个公众号后,当这个公众号有内容更新,即推送信息时,就会通知你,此时一个公众号就是一个主题,每个用户就是观察者。当你不再关注某个公众号时,则不会再通知你该公众号的相关文章。
案例
这里给出一个案例代码,这是一个对天气实时监控的模拟,当空气中环境变化时,展示板中的内容就会更新,不同的展示板可能可以展示不同的信息,这里只给出一个实例。
主题:在主题中需要有相应的注册观察者,删除观察者,通知观察者的方法
/**
* 观察者模式中的主题
*
*/
public interface Subject {
/**
* 用于注册观察者
* @param o
*/
public void registerObserver(Observer o);
/**
* 用于删除观察者
* @param o
*/
public void removeObserver(Observer o);
/**
* 用于通知所有的观察者
*/
public void notifyObserver();
}
观察者:
/**
* 观察者
*
*/
public interface Observer {
public void update(float temp,float humidity,float pressure);
}
一个展示板的基础接口:
public interface DisplayElement {
public void display();
}
具体的主题:
/**
* 一个具体的主题,当发生变化则会通知所有观察者
*
*/
public class WeatherData implements Subject {
private ArrayList observers;
private float temp,humidity,pressure;
public WeatherData() {
observers = new ArrayList<>();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if(i >= 0)
observers.remove(i);
}
@Override
public void notifyObserver() {
for(int i=0;i<observers.size();i++) {
Observer o = (Observer) observers.get(i);
o.update(temp, humidity, pressure);
}
}
/**
* 当数据更新时调用,用以通知所有的观察者
*/
public void measurementsChanged() {
notifyObserver();
}
public void setMeasurements(float temp, float humidity, float pressure) {
this.temp = temp;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
//其他方法
}
具体的观察者:
/**
* 一个具体的观察者
*
*/
public class CurrentConditionsDisplay implements Observer,DisplayElement{
private float temp;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("Current conditions: " + temp
+ "F degrees and " + humidity + "% humidity");
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temp = temp;
this.humidity = humidity;
display();
}
}
测试
public class Test {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay display = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(83, 75, 29.4f);
weatherData.setMeasurements(81, 68, 31.4f);
}
}
结果:
Current conditions: 80.0F degrees and 65.0% humidity
Current conditions: 83.0F degrees and 75.0% humidity
Current conditions: 81.0F degrees and 68.0% humidity
这样就实现了当某个主题发生变化时,观察者就能够知道这一变化,通过注册观察者能够实现添加订阅功能,而删除观察者则可以实现取消关注/订阅等功能。