研磨设计模式day11观察者模式
目录
场景
代码示例
定义
观察者模式的优缺点
本质
何时选用
简单变型-区别对待观察者
场景
我是一家报社,每当我发布一个新的报纸时,所有订阅我家报社的读者都可以接收到
代码示例
报纸对象
package day11观察者模式;import java.util.Observable;/*** 报纸对象*/
public class NewsPaper extends Observable {/*** 报纸的内容*/private String content;/*** 获取报纸的具体内容* @return 报纸的具体内容*/public String getContent() {return content;}/*** 示意,设置报纸的具体内容,相当于要出版报纸了* @param content 报纸的具体内容*/public void setContent(String content) {this.content = content;// 内容有了,说明又出新报纸了,那就通知所有的读者this.setChanged();// 然后主动通知,用的推的方式this.notifyObservers(this.content);// 如果用拉的方式,这么调用
// this.notifyObservers();}
}
读者,也就是观察者
package day11观察者模式;import java.util.Observable;
import java.util.Observer;/*** 真正的读者,也就是观察者*/
public class Reader implements Observer {/*** 读者的姓名*/private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic void update(Observable o, Object arg) {// 这里采用推的方式System.out.println(name + "收到报纸了,进行阅读。目标推过来的内容是===" + arg);// 这里是获取拉的数据
// System.out.println(name + "收到报纸了,进行阅读。主动到目标对象去拉的内容是===" + ((NewsPaper)o).getContent());}
}
client
package day11观察者模式;/*** 客户端使用*/
public class Client {public static void main(String[] args) {// 1.创建一个报纸,作为被观察者NewsPaper subject = new NewsPaper();// 2.创建阅读者,也就是观察者Reader reader1 = new Reader();reader1.setName("张三");Reader reader2 = new Reader();reader2.setName("李四");Reader reader3 = new Reader();reader3.setName("王五");// 3.注册阅读者subject.addObserver(reader1);subject.addObserver(reader2);subject.addObserver(reader3);// 4.要出报纸啦subject.setContent("本期内容是观察者模式");}
}
解析:
报社就是一个发布者,读者就是一个个订阅者,发布者提供订阅方法,每次发布者发布新的东西时,就会通知订阅者这条新的消息。
报社NewsPaper:它继承了Observable类,这个类包含了注册方法,提示改变,通知方式(推和拉)等方法,NewsPaper包含了报纸内容对象,get方法就不说了,set时会进行提示改变了,并主动通知,用的推的方式。
观察者Reader:它实现了Observer接口,实现了update方法,java实现观察者模式时默认是拉模型,如果使用推模型,那么在update这个方法里通过推拉的获取方式都可以获取到值
定义
类似发布订阅模式
观察者模式的优缺点
本质
观察者模式的本质:触发联动
在程序运行期间,通过这样的联动可以控制观察者,在update执行的时候。
何时选用
简单变型-区别对待观察者
举例:根据水质污染的严重程度来分别告知不同的管理者
思路:将水质污染当作被观察的目标,监测员、预警人员和领导就是观察者。在目标里面进行判断,满足就通知,不满足不通知。
观察者接口
1.被通知的方法2.设置观察人员的职务3.获取观察人员的职务
package day11观察者模式.高级;/*** 水质观察者接口定义*/
public interface WatcherObserver {/*** 被通知的方法* @param subject 传入被观察的目标对象*/public void update(WaterQualitySubject subject);/*** 设置观察人员的职务* @param job*/public void setJob(String job);/*** 获取观察人员的职务* @return*/public String getJob();}
观察者的具体实现
package day11观察者模式.高级;public class Watcher implements WatcherObserver{private String job;@Overridepublic void update(WaterQualitySubject subject) {// 这里采用拉的方式System.out.println(job + "获取到通知,当前污染级别为: " + subject.getPolluteLevel());}@Overridepublic void setJob(String job) {this.job = job;}@Overridepublic String getJob() {return job;}
}
目标的父对象(抽象类) :1.定义抽象是因为我们不需要全部都发消息,所以让子类去根据业务的实际需要自己去选择性的通知。2.而且在我们传入目标对象的时候具有很好的封装性,不需要对外展示具体的目标对象,传给观察者的只是目标的父抽象类。
package day11观察者模式.高级;import java.util.ArrayList;
import java.util.List;/*** 定义目标的父对象*/
public abstract class WaterQualitySubject {/*** 用来保存注册的观察者对象*/protected List<WatcherObserver> observers = new ArrayList<WatcherObserver>();/*** 注册观察者对象* @param observer 观察者对象*/public void attach(WatcherObserver observer){observers.add(observer);}/*** 删除观察者对象* @param observer*/public void detach(WatcherObserver observer){observers.remove(observer);}/*** 通知对应的观察者对象*/public abstract void notifyWatchers();/*** 获取水质污染的级别*/public abstract int getPolluteLevel();
}
目标的实现(继承目标父抽象类)
package day11观察者模式.高级;/*** 具体的检测对象*/
public class WaterQuality extends WaterQualitySubject{/*** 污染的级别,0正常 1轻度污染 2中度污染 3高度污染*/private int polluteLevel = 0;/*** 获取水质污染的级别* @return*/@Overridepublic int getPolluteLevel() {return polluteLevel;}/*** 当检测水质情况后,设置水质污染的级别* @param polluteLevel 水质污染的级别*/public void setPolluteLevel(int polluteLevel) {this.polluteLevel = polluteLevel;// 通知相应的观察者this.notifyWatchers();}/*** 通知相应的观察者对象*/@Overridepublic void notifyWatchers() {// 循环所有注册的观察者for (WatcherObserver watcher : observers) {// 开始根据污染级别判断都通知谁if (this.polluteLevel >= 0 ){// 通知监测员做记录if ("监测人员".equals(watcher.getJob())){watcher.update(this);}}if (this.polluteLevel >= 1 ){// 通知监测员做记录if ("预警人员".equals(watcher.getJob())){watcher.update(this);}}if (this.polluteLevel >= 2 ){// 通知监测员做记录if ("领导".equals(watcher.getJob())){watcher.update(this);}}}}}
client
package day11观察者模式.高级;public class Client {public static void main(String[] args) {// 创建具体的检测对象WaterQuality subject = new WaterQuality();// 创建几个观察者Watcher watcher1 = new Watcher();watcher1.setJob("监测人员");Watcher watcher2 = new Watcher();watcher2.setJob("预警人员");Watcher watcher3 = new Watcher();watcher3.setJob("领导");// 注册观察者subject.attach(watcher1);subject.attach(watcher2);subject.attach(watcher3);// 填写水质报告System.out.println("水质正常---");subject.setPolluteLevel(0);System.out.println("轻度污染---");subject.setPolluteLevel(1);System.out.println("重度污染---");subject.setPolluteLevel(2);}
}
解析:
从client开始,先创建了具体的检测对象, 他有什么用呢?可以注册观察者,可以发布通知
创建了几个观察者实现对象,给他们赋予了不同的职务。
将观察者跟目标对象进行关联,也就是注册,点进去看一下,调用了attach方法,这个方法不是具体的检测对象本身的,而是它的抽象父类中的方法
都注册进去之后,目标对象开始运行,他现在出了一个水质为0的污染报告,这个时候应该传递给谁信息呢?
点进这个setPolluteLevel(0)看一下 。这个是具体的检测对象本身的方法。
可以看出首先将传过来的值赋值给当前对象,然后调用了 this.notifyWatchers()方法。我们接着往下。
进来这个方法后,遍历所有注册到目标对象的观察者(订阅了该目标对象的订阅者),这个observers哪里来的?(),是注册而来的。
接着判断属于哪一类的污染,此时过来的污染为0,就判断当前观察者的职务是不是检测人员,如果是就调用update更新的方法,如果不是就不用管。
我们看一下update,被通知方法的接口
接下来看看它的实现
解析:判断是不是检测人员,如果是我就给他发送消息(它就能接收到消息)。
如果污染为1,那么就满足两个条件,就会给预警人员和检测人员都发送消息
相关文章:

研磨设计模式day11观察者模式
目录 场景 代码示例 定义 观察者模式的优缺点 本质 何时选用 简单变型-区别对待观察者 场景 我是一家报社,每当我发布一个新的报纸时,所有订阅我家报社的读者都可以接收到 代码示例 报纸对象 package day11观察者模式;import java.util.Observ…...

第八周第二天学习总结 | MySQL入门及练习学习第四天
实操练习: 1.建立一个员工表和与之对应的部门表 2.建立外键约束 3.使用多表查询,直接查询部门表和员工表 发现:有很多多余的因笛卡尔乘积而带来的多余输出内容 我想要的到简单明了的数据结果,要消除多于因笛卡尔乘积带来的输出…...
WPF数据转换
在基本绑定中,信息从源到目标的传递过程中没有任何变化。这看起来是符合逻辑的,但我们并不总是希望出现这种行为。通常,数据源使用的是低级表达方式,我们可能不希望直接在用户界面使用这种低级表达方式。WPF提供了两个工具&#x…...

《Go 语言第一课》课程学习笔记(十三)
方法 认识 Go 方法 Go 语言从设计伊始,就不支持经典的面向对象语法元素,比如类、对象、继承,等等,但 Go 语言仍保留了名为“方法(method)”的语法元素。当然,Go 语言中的方法和面向对象中的方…...

基于RUM高效治理网站用户体验入门-价值篇
用户体验 用户体验基本包含访问网站的性能、可用性和正确性。通俗的讲,就是一把通过用户访问测量【设计者】意图的尺子。 本文目的 网站如何传递出设计者的意图,可能页面加载时间太长、或者页面在用户的浏览器中渲染时间太慢,或者第三方设备…...
Unity之Photon PUN2开发多人游戏如何实现组队功能
前言 Photon Unity Networking 2 (PUN2) 是一款基于Photon Cloud的Unity多人游戏开发框架。它提供了一系列易于使用的API和工具,使开发者可以快速构建多人戏,并轻松处理多人游戏中的网络同步、房间管理、玩家匹配等问题。 我们在查看Pun2的Demo时,会发现Demo中自带了一个简…...

大数据Flink简介与架构剖析并搭建基础运行环境
文章目录 前言Flink 简介Flink 集群剖析Flink应用场景Flink基础运行环境搭建Docker安装docker-compose文件编写创建并运行容器访问Flink web界面 前言 前面我们分别介绍了大数据计算框架Hadoop与Spark,虽然他们有的有着良好的分布式文件系统和分布式计算引擎,有的有…...

RISC-V IOPMP实际用例-Rapid-k模型在NVIDIA上的应用
安全之安全(security)博客目录导读 2023 RISC-V中国峰会 安全相关议题汇总 说明:本文参考RISC-V 2023中国峰会如下议题,版权归原作者所有。...

【UE5】给模型指定面添加自定义材质
实现步骤 1. 首先我们向UE中导入一个简单的模型,可以看到目前该模型的材质插槽只有一个,当我们修改材质时会使得模型整体的材质全部改变,如果我们只想改变模型的某些面的材质就需要继续做后续操作。 2. 选择建模模式 3. 在模式工具栏中点击…...

mall:redis项目源码解析
文章目录 一、mall开源项目1.1 来源1.2 项目转移1.3 项目克隆 二、Redis 非关系型数据库2.1 Redis简介2.2 分布式后端项目的使用流程2.3 分布式后端项目的使用场景2.4 常见的缓存问题 三、源码解析3.1 集成与配置3.1.1 导入依赖3.1.2 添加配置3.1.3 全局跨域配置 3.2 Redis测试…...
RISC-V Linux系统kernel制作
文章目录 1、下载2、编译 1、下载 Linux 官网地址:https://www.kernel.org $ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.181.tar.xz $ tar xvf linux-5.10.181.tar.xz $ cd linux-5.10.1812、编译 安装依赖 $ sudo apt-get install -y flex bison bui…...
5G NR:PRACH时域资源
PRACH occasion时域位置由高层参数RACH-ConfigGeneric->prach-ConfigurationIndex指示,根据小区不同的频域和模式,38.211的第6.3.3节中给出了prach-ConfigurationIndex所对应的表格。 小区频段为FR1,FDD模式(paired频谱)/SUL,…...

LLaMA-2的模型架构
输入token;[B, L] 输出probs:[B, L, vab_size]...
掌握Java框架之Struts,开启高效开发之旅!
当今的软件开发世界,Java框架如Struts已经成为构建企业级应用的重要工具。Struts作为一个流行的MVC框架,不仅简化了Java Web开发,还提高了软件的可维护性和可扩展性。本文将带你走进Struts的世界,探索其魅力所在,让你领…...
关于Vue.set()
简介 Vue.set() 是 Vue 中的一个全局方法,其主要作用是向响应式对象添加新的属性,并确保新属性同样具有响应式。在 Vue.js 中,当数据对象的属性被直接修改时,Vue 可以监测到数据变化并响应变化。但若添加新的响应式对象属性时&am…...

Selenium 遇见伪元素该如何处理?
问题发生 在很多前端页面中,大家会见到很多::before、::after 元素,比如【百度流量研究院】: 比如【百度疫情大数据平台】: 以【百度疫情大数据平台】为例,“累计确诊”文本并没有显示在 HTML 源代码中&am…...
RPA技术介绍与应用价值
一、什么是RPA技术? RPA(Robotic Process Automation)机器人流程自动化,是一种能够模拟人类来执行重复性任务的新型技术。RPA可实现统筹安排、自动化业务处理,并提升业务工作流处理效率。用户只需通过图形方式显示的计算机操作界面对RPA软件进行动态设定即可。借助RPA (R…...
产品经理,需要具备哪些能力和知识
作为产品经理,需要具备以下能力和知识: 产品管理能力:具备全面的产品管理能力,包括产品策划、需求分析、产品规划、产品设计、项目管理、市场调研和竞争分析等。 用户导向思维:能够理解用户需求和期望,以…...

【C++】map和set
map和set 文章目录 map和set关联式容器setset介绍set的函数测试代码 multiset注意事项测试代码 mapmap介绍map的函数测试代码 关联式容器 前面了解过的vector,list,string等容器都是序列式容器,存储的都是元素本身,底层都是线性的…...

crawlab通过docker单节点部署简单爬虫
crawlab 单节点docker安装 此处介绍的是单节点的方式,多节点的情况可以把爬虫上传到一个节点中,之后会同步到其它节点上 version: 3.3 services:master:image: crawlabteam/crawlabcontainer_name: crawlab_masterrestart: alwaysenvironment:CRAWLAB…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...