观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象有待改变的时候,应该考虑使用观察者模式。
有个天气数据的API提供给第三方网站,要求如下:
- 提供温度、气压和湿度的接口
- 测量数据更新时,要能实时的通知给第三方
/**
* 订阅者(观察者)抽象类,自动接受输入
*/
public abstract class Observer {
//温度
protected float wenDu;
//湿度
protected float shiDu;
//气压
protected float qiYa;
/**
* 更新网站显示的天气数据
*/
public void update(float wenDu, float shiDu, float qiYa) {
this.wenDu = wenDu;
this.shiDu = shiDu;
this.qiYa = qiYa;
display();
}
public void display() {
System.out.println("温度"+wenDu);
System.out.println("湿度"+shiDu);
System.out.println("气压"+qiYa);
}
}
/**
* 发布者接口
*/
public interface Subject {
/**
* 设置数据
*/
public void setData(float wenDu, float shiDu, float qiYa);
/**
* 增加一个调用API的人
*/
public void registerObserver(Observer o);
/**
* 移除一个调用API的人
*/
public void removeObserver(Observer o);
/**
* 通知调用API的人
*/
public void notifyObservers();
}
/**
* 新浪调用天气API
*/
public class Sina extends Observer {
/**
* 还可以做其他事
*/
}
/**
* 百度调用天气API
*/
public class BaiDu extends Observer{
/**
* 还可以做其他事
*/
}
/**
* 天气API,更新时会自动推送新数据给第三方网站
*/
public class WeatherAPI implements Subject {
//温度
private float wenDu;
//湿度
private float shiDu;
//气压
private float qiYa;
private LinkedList<Observer> list;
public WeatherAPI() {
this.list = new LinkedList<Observer>();
}
@Override
public void setData(float wenDu, float shiDu, float qiYa) {
this.wenDu = wenDu;
this.shiDu = shiDu;
this.qiYa = qiYa;
//通知调用方更新天气数据
notifyObservers();
}
@Override
public void registerObserver(Observer o) {
list.add(o);
}
@Override
public void removeObserver(Observer o) {
if (list.contains(o)) {
list.remove(o);
}
}
@Override
public void notifyObservers() {
for (Observer observer : list) {
observer.update(wenDu, shiDu, qiYa);
}
}
}
public class Client {
public static void main(String[] args) {
System.out.println("新浪");
Observer sina = new Sina();
Subject weatherAPI = new WeatherAPI();
weatherAPI.registerObserver(sina);
weatherAPI.setData(16,51,999);
System.out.println("===============");
//移除新浪
weatherAPI.removeObserver(sina);
System.out.println("百度");
Observer baiDu = new BaiDu();
weatherAPI.registerObserver(baiDu);
weatherAPI.setData(22,66,666);
}
}
新浪
温度16.0
湿度51.0
气压999.0
===============
百度
温度22.0
湿度66.0
气压666.0
其实回调就是观察者模式的一种。