「这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战」
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
我们这里由一个简单的项目需求引出观察者模式:
天气预报项目需求,具体要求如下:
气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方)。需要设计开放型API,便于其他第三方也能接入气象站获取数据。
提供温度、气压和湿度的接口
测量数据更新时,要能实时的通知给第三方
通过对气象站项目的分析,我们可以初步设计出一个WeatherData类
说明:
1)通过getXxx方法,可以让第三方接入,并得到相关信息
2)当数据有更新时,气象站通过调用dataChange()去更新数据,当第三方再次获取时,就能得到最新数据,当然也可以推送。
代码实现:
// 负责提供数据
public class WeatherDate {
private float temperature;
private float pressure;
private float humidity;
private CurrentConditions currentConditions;
public WeatherDate(CurrentConditions currentConditions) {
this.currentConditions = currentConditions;
}
public float getTemperature() {
return temperature;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
//在WeatherData中,当增加一个第三方,都需要创建一个对应的第三方的公告板对象,并加入到dataChange,不利于维护,也不是动态加入
public void DataChange(){
// 调用接入方
currentConditions.update(getTemperature(),getPressure(),getHumidity());
}
public void setDate(float temperature,float pressure,float humidity){
this.temperature=temperature;
this.pressure=pressure;
this.humidity=humidity;
DataChange();
}
}
// 显示当前天气情况 类似气象站
public class CurrentConditions {
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();
}
// 显示数据
private void display() {
System.out.println("Today temperature is "+temperature);
System.out.println("Today pressure is "+pressure);
System.out.println("Today humidity is "+humidity);
}
}
普通方案——问题分析
1)其他第三方接入气象站获取数据的问题
2)无法在运行时动态的添加第三方(新浪网站)
3)违反ocp原则
观察者模式原理
观察者模式类似订牛奶业务
1)奶站/气象局:Subject
2)用户/第三方网站:Observer
Subject 登记注册、移除和通知
Observer 接收输入
registerObserver()注册removeObserver()移除notifyObservers()通知所有的注册的用户,根据不同需求,可以是更新数据,让用户来取,也可能是实施推送,看具体需求定
观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化,比如这里的奶站是subject,是1的一方。用户时Observer,是多的一方。
UMI类图

改进方案代码实现:
Subject被依赖端
public interface Subject {
public void remove(Object o);
public void notifyAllObservers();
public void registry(Object o);
}
// 负责提供数据
public class WeatherDate implements Subject {
private float temperature;
private float pressure;
private float humidity;
private List<Observer> list;// 存放依赖对象
public WeatherDate() {
this.list=new ArrayList<Observer>();
}
public void DataChange(){
// 调用接入方
notifyAllObservers();
}
@Override
public void remove(Object o) {
if(list.contains(o)) list.remove(o);
else System.out.println("删除服务失败!");
}
@Override
public void notifyAllObservers() {
for (Observer observer : list) {
observer.update(this.temperature,this.pressure,this.humidity);
}
}
@Override
public void registry(Object o) {
if(o instanceof Observer) {
Observer oo=(Observer) o;
list.add(oo);
}else{
System.out.println("添加失败!");
}
}
public void setDate(float temperature, float pressure, float humidity){
this.temperature=temperature;
this.pressure=pressure;
this.humidity=humidity;
DataChange();
}
}
Observe依赖的对象
public interface Observer {
void update(float temperature, float pressure, float humidity);
void display();
}
// 显示当前天气情况 类似气象站
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 temperature is "+temperature);
System.out.println("Today pressure is "+pressure);
System.out.println("Today humidity is "+humidity);
}
}
Client客户端
public class Client {
public static void main(String[] args) {
Observer o=new CurrentConditions();
WeatherDate weatherDate=new WeatherDate();
weatherDate.registry(o);// 注册
weatherDate.setDate(36.8f,89,78);// 数据更新
}
}
观察者模式在jdk中的应用
Subject端

Observer依赖对象

观察者模式在Jdk应用的源码分析
模式角色分析
-
observable 的作用和地位等价于我们前面讲过Subject
-
Observable是类,不是接口,类中已经实现了核心的方法,即管理Observer的方法add.. delete .. notify...
-
Observer的作用和地位等价于我们前面讲过的Observer,有update
-
Observable和 Observer的使用方法和前面讲过的一样,只是Observable是类,通过继承来说实现观察者模式