设计模式之观察者模式
什么是观察者模式
观察者模式定义了对象之间一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都能收到通知并自动刷新。
观察者模式主要包含以下几个角色:
Subject(目标):指被观察的对象,在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察。提供了一系列方法来增加,删除观察者对象,同时也定义了通知方法。目标类可以是接口也可以是抽象类。
ConcreteSubject(具体目标):目标类的子类,通常包含经常发生改变的数据,当他的状态发生改变时,向他的各个观察者发出通知。
Observer(观察者):对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法。
ConcreteObserver(具体观察者):维护了一个指定具体目标对象的引用,他存储具体观察者的有关状态,这些状态和具体目标的状态要保持一致。
观察者模式的优缺点
优点
- 可以实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样的表示层充当具体观察者。
- 在观察目标和观察者之间建立了一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无需了解具体观察者。
- 支持广播通信,观察目标会向所有已注册的观察者对象发送通知。
- 符合开闭原则,增加新的观察者对象无需修改代码。
缺点
- 如果一个观察目标对象有很多直接或间接的观察者,通知到所有的观察者会很耗时间。
- 如果在观察者和观察对象之间存在循环依赖就会触发循环调用。
观察者模式的应用场景
- 一个抽象模型有两个方面,一方面依赖于另一方面,将这两方面封装在独立的对象中使他们可以各自独立的改变。
- 一个对象的改变将导致一个或多个对象也发生改变。
观察者模式的案例
// 抽象目标类
public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();}// 具体目标类
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() {//调用 接入方的 updatenotifyObservers();}public void setData(float temperature, float pressure, float humidity) {this.temperatrue = temperature;this.pressure = pressure;this.humidity = humidity;//调用dataChange, 将最新的信息 推送给 接入方 currentConditionsdataChange();}@Overridepublic void registerObserver(Observer o) {observers.add(o);}@Overridepublic void removeObserver(Observer o) {if (observers.contains(o)) {observers.remove(o);}}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(this.temperatrue, this.pressure, this.humidity);}}}// 抽象观察者
public interface Observer {void update(float temperature, float pressure, float humidity);
}// 具体观察者
public class BaiduSite implements Observer {private float temperature;private float pressure;private float humidity;@Overridepublic 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 CurrentConditions implements Observer {private float temperature;private float pressure;private float humidity;@Overridepublic 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 static void main(String[] args) {//创建一个WeatherDataWeatherData weatherData = new WeatherData();//创建观察者CurrentConditions currentConditions = new CurrentConditions();BaiduSite baiduSite = new BaiduSite();//注册到weatherDataweatherData.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);
}
观察者模式在源码中的应用
Observer
// 抽象观察者
public interface Observer {/*** This method is called whenever the observed object is changed. An* application calls an <tt>Observable</tt> object's* <code>notifyObservers</code> method to have all the object's* observers notified of the change.** @param o the observable object.* @param arg an argument passed to the <code>notifyObservers</code>* method.*/void update(Observable o, Object arg);
}// 具体目标类
public class Observable {private boolean changed = false;// 维护了观察者集合private Vector<Observer> obs;/** Construct an Observable with zero Observers. */public Observable() {obs = new Vector<>();}public synchronized void addObserver(Observer o) {if (o == null)throw new NullPointerException();if (!obs.contains(o)) {obs.addElement(o);}}/*** Deletes an observer from the set of observers of this object.* Passing <CODE>null</CODE> to this method will have no effect.* @param o the observer to be deleted.*/public synchronized void deleteObserver(Observer o) {obs.removeElement(o);}public void notifyObservers(Object arg) {/** a temporary array buffer, used as a snapshot of the state of* current Observers.*/Object[] arrLocal;synchronized (this) {/* We don't want the Observer doing callbacks into* arbitrary code while holding its own Monitor.* The code where we extract each Observable from* the Vector and store the state of the Observer* needs synchronization, but notifying observers* does not (should not). The worst result of any* potential race-condition here is that:* 1) a newly-added Observer will miss a* notification in progress* 2) a recently unregistered Observer will be* wrongly notified when it doesn't care*/if (!changed)return;arrLocal = obs.toArray();clearChanged();}for (int i = arrLocal.length-1; i>=0; i--)((Observer)arrLocal[i]).update(this, arg);}......
}
相关文章:
设计模式之观察者模式
什么是观察者模式 观察者模式定义了对象之间一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都能收到通知并自动刷新。 观察者模式主要包含以下几个角色: Subject(目标):指被观察的对…...
Java Lambda表达式
目录1 Lambda表达式1.1 函数式编程思想概括1.2 Lambda表达式标准格式1.3 Lambda表达式练习1(抽象方法无参无返回值)1.4 Lambda表达式练习2(抽象方法带参无返回值)1.5 Lambda表达式练习2(抽象方法带参带返回值ÿ…...
【1237. 找出给定方程的正整数解】
来源:力扣(LeetCode) 描述: 给你一个函数 f(x, y) 和一个目标结果 z,函数公式未知,请你计算方程 f(x,y) z 所有可能的正整数 数对 x 和 y。满足条件的结果数对可以按任意顺序返回。 尽管函数的具体式子…...
java基础学习 day41(继承中成员变量和成员方法的访问特点,方法的重写)
继承中,成员变量的访问特点 a. name前什么都不加,name变量的访问采用就近原则,先在局部变量中查找,若没找到,继续在本类的成员变量中查找,若没找到,继续在直接父类的成员变量中查找,…...
【c语言进阶】深度剖析整形数据
🚀write in front🚀 📜所属专栏: 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对我最大的激励…...
【信息系统项目管理师】项目管理十大知识领域记忆敲出(采购风险沟通干系人)
【信息系统项目管理师】项目管理十大知识领域记忆敲出(采购风险沟通干系人) 这里写目录标题【信息系统项目管理师】项目管理十大知识领域记忆敲出(采购风险沟通干系人)一.项目采购管理记忆敲出1.合同管理:2.规划采购管…...
[LeetCode 1237]找出给定方程的正整数解
题目描述 题目链接:[LeetCode 1237]找出给定方程的正整数解 给你一个函数 f(x, y) 和一个目标结果 z,函数公式未知,请你计算方程 f(x,y) z 所有可能的正整数 数对 x 和 y。满足条件的结果数对可以按任意顺序返回。 尽管函数的具体式子未知…...
6.2 构建 RESTful 应用接口
第6章 构建 RESTful 服务 6.1 RESTful 简介 6.2 构建 RESTful 应用接口 6.3 使用 Swagger 生成 Web API 文档 6.4 实战:实现 Web API 版本控制 6.2 构建 RESTful 应用接口 6.2.1 Spring Boot 对 RESTful 的支持 Spring Boot 提供的spring-boot-starter-web组件完全…...
20230218英语学习
How Italian Artist’s Mild Colors Dominate World of Design 温柔的“莫兰迪色”,如何引领设计时尚? The Morandi color scheme has become an across-the-board fashion that now prevails in the world of design.Soft and sophisticated Morandi c…...
Linux单一服务管理systemctl
基本上systemd这个启动服务机制只有systemctl命令来处理,所以全部的操作都需要使用systemctl systemctl管理单一服务 一般来说服务的启动有两个阶段,一个是开机是否启动,以及现在是否启动 systemctl【command】【unit】 command主要有&…...
【GStreamer 】 TX1中CPU和GPU解码显示海康相机RTSP流
大家好,我是虎哥,今天找了一套海康的相机,想后续测试一下DeepStream用网络相机RTSP流做输入看看后续目标识别和分类。但是还是想先实时看看视频,当然,可以选择VLC去查看,顺道我也用GStreamer 来测试了一下&…...
匿名内部类、Lambda表达式、方法引用对比分析
文章目录一、匿名内部类1. 语法格式2. 使用方法① 传统方式② 匿名内部类方式二、Lambda表达式1. 语法格式2. 使用方法① 匿名内部类方式② Lambda表达式方式三、方法引用1. 语法格式2. 使用方法① 类型的静态方法引用② 类型的构造方法引用③ 类型的实例方法引用④ 对象的实例…...
ESXi主机CVE-2021-21972漏洞复现安全处置建议
一、漏洞简介 vSphere 是 VMware 推出的虚拟化平台套件,包含 ESXi、vCenter Server 等一系列的软件。其中 vCenter Server 为 ESXi 的控制中心,可从单一控制点统一管理数据中心的所有 vSphere 主机和虚拟机。 vSphere Client(HTML5…...
研报精选230217
目录 【行业230217毕马威】奢侈品行业新气象【行业230217国信证券】医药生物行业2023年2月投资策略:持续关注疫后复苏和创新两大主线【行业230217国金证券】航空锻造:稳定格局筑专业化壁垒,顺势而为拓产业链深度【个股230217西南证券_招商轮船…...
c++11 标准模板(STL)(std::unordered_set)(一)
定义于头文件 <unordered_set> template< class Key, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator<Key> > class unordered_set;(1)(C11 起)namespace pmr { templ…...
【C语言进阶】你听说过柔性数组吗?
👦个人主页:Weraphael ✍🏻作者简介:目前是C语言学习者 ✈️专栏:C语言航路 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞&a…...
[LeetCode]1237. 找出给定方程的正整数解
题目链接:https://leetcode.cn/problems/find-positive-integer-solution-for-a-given-equation/description/ 题目描述: 样例1: 输入:function_id 1, z 5 输出:[[1,4],[2,3],[3,2],[4,1]] 解释:functi…...
【路径规划】基于A*算法和Dijkstra算法的路径规划(Python代码实现)
👨🎓个人主页:研学社的博客💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密…...
蓝桥杯 stm32 PWM 设置占空比
本文代码使用 HAL 库。 文章目录 前言一、创建CubeMX 工程 ,占空比分析:二、相关函数:1. 获取 CNT函数2.设置CNT为 0 函数(计算器清零)3.开启TIM2_CH1的输入捕获中断函数4.TIM 回调函数三、设置上升沿,下降沿四、在lcd上显示 R40 占空比 详细代码五、设置占空比,输出 PW…...
React 合成事件理解
1 事件三个阶段 捕获、目标、处理 (具体百度,后面有空补全)2import React from "react";class Test extends React.Component {parentRef;childRef;constructor(props) {super(props);this.parentRef React.createRef();this.chil…...
202302|读书笔记——国图点滴
杂志剪影|看一本赚一本系列 anywhere 随心而行随心而动,极简相生复古文艺 热情洋溢 色彩斑斓 极致优雅 深邃魅力 新生绽放 灿若星空 异彩纷呈含苞待放 惊艳绽放 爱在云端 空中婚礼 暗夜浪漫 策马逐梦橘影相映 浆果红唇 梦幻无暇 永无止境浮光掠影 微酥清风低调奢华…...
Linux 操作系统原理 — NUMA 架构中的多线程调度开销与性能优化
目录 文章目录 目录前言NUMA 架构中的多线程性能开销1、跨 Node 的 Memory 访问开销2、跨 Core 的多线程 Cache 同步开销3、多线程上下文切换开销4、多线程模式切换开销5、中断处理的开销6、TLB 缓存失效的开销7、内存拷贝的开销NUMA 架构中的性能优化:使用多核编程代替多线程…...
OpenGL - 如何理解 VAO 与 VBO 之间的关系
系列文章目录 LearnOpenGL 笔记 - 入门 01 OpenGLLearnOpenGL 笔记 - 入门 02 创建窗口LearnOpenGL 笔记 - 入门 03 你好,窗口LearnOpenGL 笔记 - 入门 04 你好,三角形 文章目录系列文章目录1. 前言2. 渲染管线的入口 - 顶点着色器2.1 顶点着色器处理过…...
Linux中sed的使用
语法: sed [选项] [sed内置命令字符] [输入文件]选项: 参数说明-n取消默认色的输出常与sed内置命令p一起使用-i直接将修改结果写入文件,不用-i,sed修改的是内存数据-e多次编译,不需要管道符了-r支持正则扩展 sed的内…...
[软件工程导论(第六版)]第1章 软件工程学概述(复习笔记)
文章目录1.1 软件危机1.1.1 软件危机的介绍1.1.2 产生软件危机的原因1.1.3 消除软件危机的途径1.2 软件工程1.2.1 软件工程的介绍1.2.2 软件工程的基本原理1.2.3 软件工程方法学1.3 软件生命周期组成1.4 软件过程概念1.4.1 瀑布模型1.4.2 快速原型模型1.4.3 增量模型1.4.4 螺旋…...
ISP相关
Internet Service Provider,网络提供商/运营商,如电信、联通、移动等。 1. 与ISP互联的出口带宽 IDC或云提供商会与各运营商互联,互联的具体带宽数值一旦泄露,就会被恶意的攻击者利用。例如,若DDos攻击者知道了被攻击…...
vTESTstudio - VT System CAPL Functions - VT2004(续1)
成熟,就是某一个突如其来的时刻,把你的骄傲狠狠的踩到地上,任其开成花或者烂成泥。vtsStartStimulation - 启动激励输出功能:自动激励输出注意:在启动激励输出之前,一定要设置好输出模式Target:目标通道变量空间名称,例…...
WeakMap弱引用
let obj{name:张三} //{name:张三}这个对象能够被读取到,因为obj这个变量名对它的引用 //将引用覆盖掉 objnull //这个对象将会被从内存中移除,因为我们已经失去了对他的所有引用 let obj{name:张三} let arr[obj] objnull //对象{name:张三}不会…...
Springboot 使用quartz 定时任务 增删改查
前段时间公司项目用到了 定时任务 所以写了一篇定时任务的文章 ,浏览量还不错 , Springboot 整合定时任务 ) 所以就准备写第二篇, 如果你是一名Java工程师,你也可以会看到如下的页面 ,去添加定时任务 定时任务展示 :…...
华为OD机试 - 猜字谜(Python) | 机试题+算法思路 【2023】
最近更新的博客 华为OD机试 - 热点网络统计 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 查找单入口空闲区域 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 好朋友 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 找出同班小朋友 | 备考思路,刷题要点…...
做花酒的网站/广告推广计划
摘要:大数据时代已经到来。现阶段,我国大数据产业发展如何?大数据应用领域在哪?大数据价值在哪里?带着这些疑问,走进大数据,感受大数据带来的神奇魔力。关注作者:需要大数据学习视频…...
微信咋做自己的网站/宣传软文模板
184行前添加: if (asm.GetType().FullName ! "System.Reflection.RuntimeAssembly") continue;忽略错误 缓存的Provider 不能执行 存储过程,报 NotSupportedException("Command tree type " commandTree.GetType() " is not …...
wap网页编写/seo新人怎么发外链
1. 创建版本库 1.1 创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录: 1.2通过git init命令把这个目录变成Git可以管理的仓库(git进入空目录的路径) $ git init Initialized empty Git repo…...
韩国网站加速器/如何让百度收录网址
安装Python包python-pptx需要用到lxml,而安装lxml报错: fatal error: libxml/xmlversion.h file not found 解决方法: xcode-select --install 安装完commandline tool for xcode后,在安装就不会出错了。 本文转自 h2appy 51CTO博…...
做网站运营好还是SEO好/网站登录入口
怎么设置legacy启动?现在新型电脑都是采用uefi gpt启动模式,以适应win8、win10这些新型操作系统,不过win7之前的系统大多不支持uefi,而是采用legacy启动模式,硬盘分区表是MBR,而不是GPT,如果要在…...
网站是怎么做排名的/做网页设计一个月能挣多少
<?php include_once smarty.php; $smarty->assign(title,标题); $smarty->assign(content,内容);$output $smarty->fetch(index.html); echo $output;// $smarty->display(index.html); ?>#使用fetch函数,你可以将要输出的html赋值给一个变量&…...