一、定义
观察者模式也叫发布订阅模式。
在对象之间定义一个一对多的依赖,当一个对象状态发生改变的时候,所有依赖的对象都会自动收到通知。
被依赖的对象是Subject(主题,也叫被观察者),依赖的对象是Observer(观察者)。
二、原理类图
(1)抽象主题(Subject):
它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
(2)具体主题(Concrete Subject):
将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
(3)抽象观察者(Observer):
为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
(4)具体观察者(Concrete Observer):
实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
三、案例
1、需求
天气预报项目需求,具体要求如下:
(1)气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如 发布到自己的网站或第三方)。
(2)需要设计开放型API,便于其他第三方也能接入气象站获取数据。
(3)提供温度、气压和湿度的接口
(4) 测量数据更新时,要能实时的通知给第三方
2、代码实现
//接口, 让具体主题类WeatherData 来实现
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
//观察者接口,有观察者来实现
public interface Observer {
public void update(float temperature, float pressure, float humidity);
}
/**
* 类是核心
* 1. 包含最新的天气情况信息
* 2. 含有 观察者集合,使用ArrayList管理
* 3. 当数据有更新时,就主动通知所有的(接入方)就看到最新的信息
* @author Administrator
*
*/
public class WeatherData implements Subject {
private float temperatrue;
private float pressure;
private float humidity;
// 观察者集合
private ArrayList<Observer> observers;
public WeatherData() {
observers = new ArrayList<Observer>();
}
public float getTemperature() {
return temperatrue;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
// 当数据有更新时,就调用 setData
public void setData(float temperature, float pressure, float humidity) {
this.temperatrue = temperature;
this.pressure = pressure;
this.humidity = humidity;
// 调用notifyObservers, 将最新的信息 推送给观察者
notifyObservers();
}
// 注册一个观察者
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
// 移除一个观察者
@Override
public void removeObserver(Observer o) {
if (observers.contains(o)) {
observers.remove(o);
}
}
// 遍历所有的观察者,并通知
@Override
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
observers.get(i).update(this.temperatrue, this.pressure, this.humidity);
}
}
}
public class CurrentConditions implements Observer {
// 温度,气压,湿度
private float temperature;
private float pressure;
private float humidity;
// 更新 天气情况,是由 WeatherData 来调用,我使用推送模式
public void update(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
// 显示
public void display() {
System.out.println("***Today mTemperature: " + temperature + "***");
System.out.println("***Today mPressure: " + pressure + "***");
System.out.println("***Today mHumidity: " + humidity + "***");
}
}
public class BaiduSite implements Observer {
// 温度,气压,湿度
private float temperature;
private float pressure;
private float humidity;
// 更新 天气情况,是由 WeatherData 来调用,我使用推送模式
public void update(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
// 显示
public void display() {
System.out.println("===百度网站====");
System.out.println("***百度网站 气温 : " + temperature + "***");
System.out.println("***百度网站 气压: " + pressure + "***");
System.out.println("***百度网站 湿度: " + humidity + "***");
}
}
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 创建一个WeatherData
WeatherData weatherData = new WeatherData();
// 创建观察者
CurrentConditions currentConditions = new CurrentConditions();
BaiduSite baiduSite = new BaiduSite();
// 注册到weatherData
weatherData.registerObserver(currentConditions);
weatherData.registerObserver(baiduSite);
// 测试
System.out.println("通知各个注册的观察者, 看看信息");
weatherData.setData(10f, 100f, 30.3f);
weatherData.removeObserver(currentConditions);
// 测试
System.out.println();
System.out.println("通知各个注册的观察者, 看看信息");
weatherData.setData(10f, 100f, 30.3f);
}
}
4、好处
(1) 使用观察者模式设计,就可以用集合的方式来管理用户(Observer),包括注册,移除 和通知。
(2)这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核 心类WeatherData不会修改代码,遵守了ocp原则。
四、应用
Jdk的Observable类和Observer接口就使用了观察者模式
(1)Observable 的作用和地位等价于 我们前面讲过 Subject
(2)Observable 是类,不是接口,类中已经实现了核心的方法,即管理Observer的方法add()、delete()、notify()
(3)Observer 的作用和地位等同于我们前面讲过的 Observer,定义了抽象方法 update()
(4)Observable 和 Observer 的使用方法和前面讲过的一样,只是Observable 是类,通过继承来管理观察者,实现观察者模式。
关注私信可获取更多详细课程资料