java 观察者模式_图解Java设计模式之观察者模式

图解Java设计模式之观察者模式

    • 天气预报项目需求
    • 天气预报设计方案 1 - 普通方案
    • 观察者模式(Observer)原理
    • 观察者模式解决天气预报需求
    • 观察者模式在JDK应用的源码分析

天气预报项目需求

1)气象站可以将每天测量到的湿度、温度、气压等等以公告的形式发布出去(比如发布到自己的网站或第三方)。
2)需要设计开放型API,便于其他第三方也能接入气象站获取数据。
3)提供温度、气压和湿度的接口。
4)测量数据更新时,要能实时的通知给第三方。

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

通过对气象站项目的分析,设计出一个WeatherData类

b95a6e252eed8353d2377ac004fed91e.png


说明 :
1)通过getXxx方法,可以让第三方接入,并得到相关信息。
2)当数据有更新时,气象站通过调用dataChange()去更新数据,当第三方再次获取时,就能得到最新数据,当然也可以推送。

762ad4d79ee4f0e2004d9959b62bb0d5.png


CurrentConditions(当前的天气情况)
// 推送
可以理解成是我们气象局的网站

package 

问题分析 :
1)其他第三方接入气象站获取数据的问题
2)无法在运行时动态的添加第三方(新浪网站)
3)违反ocp原则 -》观察者模式
在WeatherData中,当增加一个第三方,都需要创建一个对应的第三方的公告板对象,并加入到dataChange,不利于维护,也不是动态加入。
public void dataChange() {
currentConditions.update(getTemperature(),getPressure(),getHumidity());
}

观察者模式(Observer)原理

观察者模式类似订牛奶业务
1)奶站/气象局 :Subject
2)用户/第三方网站 :Observer
Subject :登记注册、移除和通知

11d4bc14480ce8d8effce2afbb749dee.png


1)registerObserver 注册
2)removeObserver 移除
3)notifyObservers() 通知所有的注册的用户,根据不同需求,可以是更新数据,让用户来取,也可能是实时推送,看具体需求定。
Observer :接收输入
观察者模式 :对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化,比如这里的奶站是Subject,是1的一方。用户是Observer,是多的一方。

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

369de60c94f20bb8ed403055a7ba5d2c.png
package com.example.demo.observer.improve;/*** 观察者接口,有观察者来实现* @author zhaozhaohai**/
public interface Observer {public void update(float temperatrue, float pressure, float humidity);}
package com.example.demo.observer.improve;public interface Subject {public void registerObserver(Observer observer);public void removeObserver(Observer observer);public void notifyObservers();}
package com.example.demo.observer.improve;//显示当前天气情况(可以理解成是气象站自己的网站)
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 + "***");}
}
package com.example.demo.observer.improve;import java.util.ArrayList;
import java.util.List;/*** 类是核心* 1. 包含最新的天气情况信息* 2. 含有 观察者集合,使用ArrayList管理* 3. 当数据有更新时,就主动的调用 ArrayList,通知所有的(接入方)就看到最新的信息。* @author zhaozhaohai**/
public class WeatherData implements Subject{private float temperatrue;private float pressure;private float humidity;private List<Observer> observers;public WeatherData() { this.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());notifyObservers();}//当数据有更新时,就调用 setDatapublic void setData(float temperature, float pressure, float humidity) {this.temperatrue = temperature;this.pressure = pressure;this.humidity = humidity;//调用 dataChange, 将最新的信息 推送给 接入方 currentConditions dataChange();}/*** 注册一个观察者*/@Overridepublic void registerObserver(Observer observer) {// TODO Auto-generated method stubobservers.add(observer);}/*** 移除一个观察者*/@Overridepublic void removeObserver(Observer observer) {// TODO Auto-generated method stubobservers.remove(observer);}/*** 遍历所有的观察者,并通知*/@Overridepublic void notifyObservers() {// TODO Auto-generated method stubobservers.stream().forEach(item -> {item.update(temperatrue, pressure, humidity);});}
}
package com.example.demo.observer.improve;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("***百度网站 气温: " + temperature + "***"); System.out.println("***百度网站 气压: " + pressure + "***"); System.out.println("***百度网站 湿度: " + humidity + "***");}}
package com.example.demo.observer.improve;public class Client {public static void main(String[] args) {// TODO Auto-generated method stub// 创建一个WeatherDataWeatherData weatherData = new WeatherData();// 创建观察者CurrentConditions currentConditions = new CurrentConditions();BaiduSite baiduSite = new BaiduSite();// 注册到weatherDataweatherData.registerObserver(currentConditions);weatherData.registerObserver(baiduSite);// 测试System.out.println(" 通知各个注册的观察者,看看信息 ");weatherData.setData(10f, 11f, 12f);}}

观察者模式的好处 :
1)观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册、移除和通知。
2)这样,我们增加观察者(可以理解为一个新的公告板),就不需要去修改核心类WeatherData不会修改代码,遵守类ocp原则。

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

e3fca958ad9420cfa7d40ffd064c614f.png

e5766961a16913ddb48bd5009ca1c129.png

73be4656ce6753679c68b80eef89be39.png


模式角色分析 :
1)Observable 的作用和地位等价于,前面的Subject
2)Observable 是类,不是接口,类中已经实现类核心的方法,即管理Observer的方法 add… delete… notify…
3)Observer 的作用和地位等价于前面的 Observer的update
4)Observable 和 Observer 的使用方法一样,只是Observable是类,通过继承来实现观察者模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/430972.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么在同一页中分页_分库分表业界难题,跨库分页的几种常见方案

为什么需要研究跨库分页&#xff1f;互联网很多业务都有分页拉取数据的需求&#xff0c;例如&#xff1a;(1)微信消息过多时&#xff0c;拉取第N页消息&#xff1b;(2)京东下单过多时&#xff0c;拉取第N页订单&#xff1b;(3)浏览58同城&#xff0c;查看第N页帖子&#xff1b;…

content add tpl.php,phpcms后台批量上传添加图片文章方法详解(一)

注&#xff1a;以下所有代码中&#xff0c;红色部分为增加部分。一、在后台增加批量添加按钮打开“phpcms\modules\content\templates\content_list.tpl.php”文件搜索“$category[‘catname‘]));?>”在这句话的后天的添加&#xff1a;a echo"" href":;&q…

sap 供应商表_财务人员学习SAP的路线图

有许多网友在公众号给我们留言&#xff0c;咨询财务人员学习SAP的事情&#xff0c;如何才能快速掌握SAP&#xff0c;有没有捷径什么的。今天就给大家分享一下财务人员学习SAP的经验&#xff0c;希望能够为财务人员揭开SAP神秘的面纱&#xff0c;学习SAP少走弯路。刚接触SAP的财…

nodejs搭配phantomjs highcharts后台生成图表

简单分享一下&#xff0c;后台使用nodejs结合highcharts、phantomjs生成报表图片的方法。这主要应用在日报邮件。 主要参考以下资料&#xff1a; http://www.highcharts.com/component/content/article/2-news/52-serverside-generated-charts#phantom_usagehttps://bitbucket.…

vue 页面切换动画_Flutter Hero动画让你的APP页面切换充满动效 不一样的体验 不一样的细节处理...

优美的应用体验 来自于细节的处理&#xff0c;更源自于码农的自我要求与努力&#xff0c;当然也需要码农年轻灵活的思维。本文章实现的Demo效果&#xff0c;如下图所示&#xff1a;class HeroHomePage extends StatefulWidget { override _TestPageState createState() > …

自定义左右侧滑菜单

实现效果&#xff1a; 左右侧滑菜单&#xff0c;侧滑栏占主屏比为60%监听触控&#xff0c;自定义滑动动画&#xff0c;当侧边栏滑动超过50%松开触控将自动滑动到60%&#xff0c;未超过50%松开触控回归侧边栏隐藏为主屏设置蒙版效果&#xff0c;根据侧滑菜单的占屏比设置主屏蒙版…

ubuntu php7 memcache,linux上安装php7 memcache扩展

php7安装memcache扩展需要memcache php7的分支 否则安装会失败php7的memcache扩展安装&#xff0c;真的很让人心碎&#xff01;下面则是php7的扩展memcache安装了。用之前的php版本安装是没有问题&#xff0c;但是用了php7安装 http://pecl.php.net/package/memcache 下的任一…

好文推荐系列--------(3)GruntJS 在线重载 提升生产率至新境界

好文原文地址&#xff1a;http://segmentfault.com/a/1190000000354555 本文将首先介绍grunt-markdown插件如何配合HTML模板使用&#xff0c;接着我将介绍如何使用grunt-watch插件将工作效率提升至新层次。如果你不熟悉GruntJS&#xff0c;请先阅读我关于GruntJS的文章。 Githu…

二叉树的创建_大多数人都不会手写创建并遍历二叉树,一航这里帮你终结了

创建二叉树、遍历二叉树、二叉树的最近公共祖先任何疑问、意见、建议请公众号留言或联系qq474356284先序、后序创建二叉树先中后层序遍历二叉树二叉树的最近公共祖先 输入格式&#xff1a;创建二叉树时的输入&#xff1a;如序列&#xff1a;{1 2 -1 -1 3 -1 -1}表示1结点有2,…

zookeeper 密码_阿里资深JAVA架构带你深度剖析dubbo和zookeeper关系

为什么要用dubbo&#xff1f;当网站规模达到了一定的量级的时候&#xff0c;普通的MVC框架已经不能满足我们的需求&#xff0c;于是分布式的服务框架和流动式的架构就凸显出来了。单一应用架构当网站流量很小时&#xff0c;只需一个应用&#xff0c;将所有功能都部署在一起&…

nw.js FrameLess Window下的窗口拖拽与窗口大小控制

nw.js FrameLess Window下的窗口拖拽与窗口大小控制 很多时候&#xff0c;我们觉得系统的Frame框很难看&#xff0c;于是想自定义。 自定义Frame的第一步是在package.config文件中将frame选项设置为false。 { "name": "1", "main": "index.…

linux 文件重命名_如何在 Linux 上重命名一组文件 | Linux 中国

要用单个命令重命名一组文件&#xff0c;请使用 rename 命令。它需要使用正则表达式&#xff0c;并且可以在开始前告诉你会有什么更改。-- Sandra Henry-stocker几十年来&#xff0c;Linux 用户一直使用 mv 命令重命名文件。它很简单&#xff0c;并且能做到你要做的。但有时你需…

oracle插入性能优化,Oracle-insert性能优化

看见朋友导入数据&#xff0c;花了很长时间都没完成&#xff01;其实有很多快速的方法&#xff0c;整理下&#xff01; 向表中插入数据有很多办法,但是方法不同&#xff0c;性能差别很看见朋友导入数据&#xff0c;&#xff0c;花了很长时间都没完成&#xff01;其实有很多快速…

dba_segments和dba_tables的不同

create table tset as select * from dba_objects; select count(*) from tset; select table_name,blocks,empty_blocks from dba_tables where table_name’TSET’; select segment_name,bytes,blocks,extents from dba_segments where segment_name’TSET’; 问题来了&#…

微博air客户端_打磨近十年,接近「完美」的 macOS 第三方微博客户端:Maipo

2020年11月13日&#xff0c;macOS Big Sur正式推送当天&#xff0c;Maipo for 微博也迎来了4.0.0大版本更新。从Weibo for Mac&#xff08;2011年&#xff09;、WeiboX&#xff08;2014年&#xff09;到Maipo&#xff08;2017年&#xff09;&#xff0c;跨度近十年&#xff0c;…

输入框联动查询

目的&#xff1a;类似于百度的搜索联动&#xff0c;输入前面的几个字&#xff0c;查询出可能的结果供用户选择&#xff0c;如下&#xff1a; html部分&#xff1a;在“中”这个输入框下面隐藏一个ul属性&#xff0c;例如: <ul class"am-padding-left-0 uhide" id&…

LoadRunner函数

一、基础函数简介 在VU左边导航栏中&#xff0c;有三个LoadRunner框架函数&#xff0c;分别是vuser_init()、Action()、vuser_end()。这三个函数存在于任何Vuser类型的脚本中。 vuser_init:虚拟用户的初始化函数&#xff0c;一般将用户初始化的操作放在这里&#xff0c;如登录操…

TPLink 备份文件bin文件解析

TPLink 路由器备份文件bin文件 测试路由器 WR885&#xff0c;备份文件加密方式DES&#xff0c;密钥&#xff1a;478DA50BF9E3D2CF linux端&#xff1a; openssl enc -d -des-ecb -nopad -K 478DA50BF9E3D2CF -in config.bin python&#xff1a; python默认没有安装crypto需要自…

linux的文件搜索命令,Linux文件搜索命令find的用法 | 术与道的分享

不管在Windows还是Linux中&#xff0c;最重要的问题不是说你能搜索到这个文件&#xff0c;而是最好少用搜索&#xff0c;应该是你在整个服务器的规划里面&#xff0c;把所以的文件目录规划的很好。就像如果你在家里找衣服&#xff0c;如果不是你乱扔&#xff0c;就不可能花费太…

vue v-if判断数组元素的值_Vue项目上线做的一些基本优化

前言本文主要是做一个Vue性能优化的帖子&#xff0c;做一个参考文档&#xff0c;对以后项目上线做一些集合文档。如果对各位在项目优化时&#xff0c;做一个文档参照。开发过程在开发项目的时候&#xff0c;就要注意项目的一些小技巧&#xff0c;下面我就罗列一些经常用到的优化…