1 天气预报项目需求,具体要求如下:

1) 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方)。

2) 需要设计开放型 API,便于其他第三方也能接入气象站获取数据。

3) 提供温度、气压和湿度的接口

4) 测量数据更新时,要能实时的通知给第三方

2 天气预报设计方案 1-普通方案

WeatherData 类

  • 传统的设计方案

  • 代码实现
package com.lin.observer;

/**
* 显示当前天气情况(可以理解为气象站的网站)
* @Description:
* @author LinZM
* @date 2021-2-7 12:49:27
* @version V1.8
*/
public class CurrentConditions { // 温度,气压,湿度
private float temperatrue; private float pressure; private float humidity; // 更新天气情况
public void update(float temperature, float pressure, float humidity) {
this.temperatrue = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
} public void display(){
System.out.println("===Today's temperature: "+temperatrue+"===");
System.out.println("===Today's pressure: "+pressure+"===");
System.out.println("===Today's humidity: "+humidity+"===");
} }
package com.lin.observer;

/*
* 类是核心 1. 包含最新的天气情况信息 2. 含有 CurrentConditions 对象 3. 当数据有更新时,就主动的调用
* CurrentConditions 对象 update 方法(含 display), 这样他们(接入方)就看到最新的信息
*/ public class WeatherData { private float temperatrue;
private float pressure;
private float humidity;
private CurrentConditions currentConditions; //加入新的第三方 public WeatherData(CurrentConditions currentConditions) {
this.currentConditions = currentConditions;
} public float getTemperature() {
return temperatrue;
} public float getPressure() {
return pressure;
} public float getHumidity() {
return humidity;
} public void dataChange() { //调用 接入方的 update
currentConditions.update(getTemperature(), getPressure(), getHumidity());
} //当数据有更新时,就调用 setData
public void setData(float temperature, float pressure, float humidity) {
this.temperatrue = temperature;
this.pressure = pressure;
this.humidity = humidity;
//调用 dataChange, 将最新的信息 推送给 接入方 currentConditions
dataChange();
}
}
package com.lin.observer;

public class Client {

    public static void main(String[] args) {

        CurrentConditions currentConditions = new CurrentConditions();
WeatherData weatherData = new WeatherData(currentConditions);
weatherData.setData(10, 20, 3); }
}

  • 问题分析

1) 其他第三方接入气象站获取数据的问题

2) 无法在运行时动态的添加第三方 (新浪网站)

3) 违反 ocp 原则=>观察者模式

//在 WeatherData 中,当增加一个第三方,都需要创建一个对应的第三方的公告板对象,并加入到 dataChange, 不利于维护,也不是动态加入

public void dataChange() {

currentConditions.update(getTemperature(), getPressure(), getHumidity());

}

3 观察者模式原理

1) 观察者模式类似订牛奶业务

2) 奶站/气象局:Subject

3) 用户/第三方网站:Observer

  • Subject:登记注册、移除和通知

1) registerObserver 注 册

2) removeObserver 移 除

3) notifyObservers() 通知所有的注册的用户,根据不同需求,可以是更新数据,让用户来取,也可能是实施推送, 看具体需求定

  • Observer:接收输入
  • 观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为 Subject,依赖的对象为 Observer,Subject

通知 Observer 变化,比如这里的奶站是 Subject,是 1 的一方。用户时 Observer,是多的一方。

4 观察者模式解决天气预报需求

类图说明

代码实现

package com.lin.observer.plus;

public interface Subject {

    void registerObserver(Observer o);

    void removeObserver(Observer o);

    void notifyObserver();

}
package com.lin.observer.plus;

import java.util.ArrayList;

/*
* 类是核心 1. 包含最新的天气情况信息 2. 含有 CurrentConditions 对象 3. 当数据有更新时,就主动的调用
* CurrentConditions 对象 update 方法(含 display), 这样他们(接入方)就看到最新的信息
*/ 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;
} public void dataChange() { //调用 接入方的 update
//currentConditions.update(getTemperature(), getPressure(), getHumidity());
notifyObserver();
} //当数据有更新时,就调用 setData
public void setData(float temperature, float pressure, float humidity) {
this.temperatrue = temperature;
this.pressure = pressure;
this.humidity = humidity;
//调用 dataChange, 将最新的信息 推送给 接入方 currentConditions
dataChange();
} @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 notifyObserver() {
for (int i = 0; i < observers.size(); i++) {
observers.get(i).update(temperatrue, pressure, humidity);
}
}
}
package com.lin.observer.plus;

public interface Observer {

    void update(float temperatrue, float pressure, float humidity);

}
package com.lin.observer.plus;

public class CurrentConditions implements Observer{

        // 温度,气压,湿度
private float temperatrue; private float pressure; private float humidity; // 更新天气情况
public void update(float temperature, float pressure, float humidity) {
this.temperatrue = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
} public void display(){
System.out.println("===Today's temperature: "+temperatrue+"===");
System.out.println("===Today's pressure: "+pressure+"===");
System.out.println("===Today's humidity: "+humidity+"===");
} }
package com.lin.observer.plus;

public class BaiDu implements Observer{

    // 温度,气压,湿度
private float temperatrue; private float pressure; private float humidity; // 更新天气情况
public void update(float temperature, float pressure, float humidity) {
this.temperatrue = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
} public void display() {
System.out.println("===BaiDu's temperature: " + temperatrue + "===");
System.out.println("===BaiDu's pressure: " + pressure + "===");
System.out.println("===BaiDu's humidity: " + humidity + "===");
} }
package com.lin.observer.plus;

public class Client {

    public static void main(String[] args) {
// 创建一个WeatherData
WeatherData weatherData = new WeatherData(); // 创建观察者
CurrentConditions currentConditions = new CurrentConditions();
BaiDu baiDu = new BaiDu(); // 注册
weatherData.registerObserver(currentConditions);
weatherData.registerObserver(baiDu); // 测试
System.out.println("通知各个注册的观察者:");
weatherData.setData(23, 12, -0.4f);
}
}

 观察者模式的好处

1) 观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知。

2) 这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类 WeatherData 不会修改代码, 遵守了 ocp 原则。

5 观察者模式在 Jdk 应用的源码分析

1) Jdk 的 Observable 类就使用了观察者模式

2) 代码分析+模式角色分析

3) 模式角色分析

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

仅供参考,有错误还请指出!

有什么想法,评论区留言,互相指教指教。

最新文章

  1. 函数式编程之柯里化(curry)
  2. Python演讲笔记1
  3. 关于Git的网址
  4. LoadRunner测试结果分析02 转载至zhangzhe的新浪博客
  5. fis3使用环境
  6. Contains Duplicate II
  7. 获取Assets目录下的图片显示并上传
  8. Good Bye 2015 B. New Year and Old Property 计数问题
  9. Latex 常用知识点存档
  10. 让Tomcat支持中文路径名和中文文件名
  11. 使用 HTML5 input 类型提升移动端输入体验(键盘)
  12. MySQL Crash Errcode: 28 - No space left on device
  13. 搬瓦工搭建SS的教程
  14. bmob云代码中生成缩略图
  15. Jenkins pipeline 并行执行任务流
  16. C# System.IO.StreamWriter
  17. zabbix使用自定义key进行监控
  18. Linux paste命令详解
  19. ACM__01背包,完全背包,多重背包
  20. 看起来像是PS的照片,实际上却令人难以置信!

热门文章

  1. ps 2020 下载
  2. 【Oracle】B-tree和函数索引
  3. 【ORACLE】awr报告问题分析
  4. 检查Mysql主从状态
  5. ModelForm的基本用法:
  6. Linux中让终端输入变为非阻塞的三种方法
  7. 聊一聊:Service层你觉得有用吗?
  8. 解决 browser-sync start --server --files 文件不能同步的问题!
  9. 僵尸网络(botnet)概念浅析
  10. libuv事件循环中的三种句柄