观察者模式
- 我是一名大三本科生,专业是软件工程【一本】。目前,正在准备找实习以及秋招,意向岗位是Java后端开发工程师。为此,在码云托管了一个项目,以整理我所有所学知识。涉及内容:计算机网络、操作系统、Java基础、主流Java后端框架、设计模式、Web前端框架等内容。欢迎大家访问我的开源项目编程之路
- 码云地址:https://gitee.com/alizipeng/the-way-of-programming
- 以下内容均记载在我的开源项目中
0. 简介
定义对象间的一对多的关系。当一个对象【被观察者】的状态发生变化时,所有依赖于它的对象【观察者们】都将得到通知并自动更新。
1. 场景设定
天气预报项目需求:
- 气象站可以将每天测量的温度、湿度、气压等等以公告的形式发布出去【如,发布到自己的网站或者第三方】。
- 需要设计开放性API,便于其他第三方也能接入气象站获取数据。
- 提供温度、气压和湿度的接口。
- 测量数据更新时,要能实时的通知给第三方。
2. 类结构设计
2.1 Subject接口
/**
* @author: zipeng Li
* 2021/5/17 16:29
*/
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
2.2 WeatherData类
/**
* @author: zipeng Li
* 2021/5/17 15:44
*/
public class WeatherData implements Subject {
// 温度
private float temperatrue;
// 气压
private float pressure;
// 湿度
private float humidity;
// 接入方列表
private ArrayList<Observer> observers;
public WeatherData() {
this.observers = new ArrayList<>();
}
public float getTemperature() {
return temperatrue;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
public void dataChange() {
notifyObservers();
}
// 当数据有更新时,调用此方法。
// 该方法将调用推送方法,实时推送到接入方
public void setData(float temperature, float pressure, float humidity) {
this.temperatrue = temperature;
this.pressure = pressure;
this.humidity = humidity;
dataChange();
}
@Override
public void registerObserver(Observer o) {
if(!observers.contains(o)){
observers.add(o);
}
}
@Override
public void removeObserver(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for(Observer item: observers){
item.update(this.temperatrue, this.pressure, this.humidity);
}
}
}
2.3 Observer接口
/**
* @author: zipeng Li
* 2021/5/17 16:30
*/
public interface Observer {
void update(float temperature, float pressure, float humidity);
}
2.4 Observer实现类
/**
* @author: zipeng Li
* 2021/5/17 16:39
*/
public class BaiduObserver implements Observer {
private float temperature;
private float pressure;
private float humidity;
@Override
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("***Today mTemperature: " + temperature + "***");
System.out.println("***Today mPressure: " + pressure + "***");
System.out.println("***Today mHumidity: " + humidity + "***");
}
}
/**
* 天气信息接入方
*
* @author: zipeng Li
* 2021/5/17 15:45
*/
public class CurrentConditions implements Observer {
private float temperature;
private float pressure;
private float humidity;
@Override
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("接入方:CurrentConditions");
System.out.println("***Today mTemperature: " + temperature + "***");
System.out.println("***Today mPressure: " + pressure + "***");
System.out.println("***Today mHumidity: " + humidity + "***");
}
}
2.5 测试结果
/**
* @author: zipeng Li
* 2021/5/17 15:46
*/
public class InternetWeather {
public static void main(String[] args) {
// 创建接入方
Observer currentConditions = new CurrentConditions();
Observer baiduObserver = new BaiduObserver();
// 创建气象站
WeatherData weatherData = new WeatherData();
// 接入方注册到气象站
weatherData.registerObserver(currentConditions);
weatherData.registerObserver(baiduObserver);
// 更新气象信息
weatherData.setData(1.0f, 2.0f, 3.0f);
}
}
3. 优点解析
- 观察者模式遵循开闭原则【ocp原则】 扩展性良好,若新增了第三方接入对象,则只需要实现Observer接口并重写update方法,最后注册到气象站,即可完成接入。
- 以集合的方式来管理观察者,包含注册、移除和通知三大核心功能。
4. 在JDK中的应用
分析:
- Observable 相当于
Subject接口
。实现了核心的方法,即管理Observer的方法 add… delete…notify…- Observer接口相当于上述例子的
Observer接口
- JDK中的Observable类与Observer接口的使用方式大同小异,差异的地方是
Observable
是类,需要使用继承来实现观察者模式