当前位置: 首页 > news >正文

研磨设计模式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观察者模式

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

第八周第二天学习总结 | MySQL入门及练习学习第四天

实操练习&#xff1a; 1.建立一个员工表和与之对应的部门表 2.建立外键约束 3.使用多表查询&#xff0c;直接查询部门表和员工表 发现&#xff1a;有很多多余的因笛卡尔乘积而带来的多余输出内容 我想要的到简单明了的数据结果&#xff0c;要消除多于因笛卡尔乘积带来的输出…...

WPF数据转换

在基本绑定中&#xff0c;信息从源到目标的传递过程中没有任何变化。这看起来是符合逻辑的&#xff0c;但我们并不总是希望出现这种行为。通常&#xff0c;数据源使用的是低级表达方式&#xff0c;我们可能不希望直接在用户界面使用这种低级表达方式。WPF提供了两个工具&#x…...

《Go 语言第一课》课程学习笔记(十三)

方法 认识 Go 方法 Go 语言从设计伊始&#xff0c;就不支持经典的面向对象语法元素&#xff0c;比如类、对象、继承&#xff0c;等等&#xff0c;但 Go 语言仍保留了名为“方法&#xff08;method&#xff09;”的语法元素。当然&#xff0c;Go 语言中的方法和面向对象中的方…...

基于RUM高效治理网站用户体验入门-价值篇

用户体验 用户体验基本包含访问网站的性能、可用性和正确性。通俗的讲&#xff0c;就是一把通过用户访问测量【设计者】意图的尺子。 本文目的 网站如何传递出设计者的意图&#xff0c;可能页面加载时间太长、或者页面在用户的浏览器中渲染时间太慢&#xff0c;或者第三方设备…...

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,虽然他们有的有着良好的分布式文件系统和分布式计算引擎&#xff0c;有的有…...

RISC-V IOPMP实际用例-Rapid-k模型在NVIDIA上的应用

安全之安全(security)博客目录导读 2023 RISC-V中国峰会 安全相关议题汇总 说明&#xff1a;本文参考RISC-V 2023中国峰会如下议题&#xff0c;版权归原作者所有。...

【UE5】给模型指定面添加自定义材质

实现步骤 1. 首先我们向UE中导入一个简单的模型&#xff0c;可以看到目前该模型的材质插槽只有一个&#xff0c;当我们修改材质时会使得模型整体的材质全部改变&#xff0c;如果我们只想改变模型的某些面的材质就需要继续做后续操作。 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指示&#xff0c;根据小区不同的频域和模式&#xff0c;38.211的第6.3.3节中给出了prach-ConfigurationIndex所对应的表格。 小区频段为FR1&#xff0c;FDD模式(paired频谱)/SUL&#xff0c;…...

LLaMA-2的模型架构

输入token&#xff1b;[B, L] 输出probs:[B, L, vab_size]...

掌握Java框架之Struts,开启高效开发之旅!

当今的软件开发世界&#xff0c;Java框架如Struts已经成为构建企业级应用的重要工具。Struts作为一个流行的MVC框架&#xff0c;不仅简化了Java Web开发&#xff0c;还提高了软件的可维护性和可扩展性。本文将带你走进Struts的世界&#xff0c;探索其魅力所在&#xff0c;让你领…...

关于Vue.set()

简介 Vue.set() 是 Vue 中的一个全局方法&#xff0c;其主要作用是向响应式对象添加新的属性&#xff0c;并确保新属性同样具有响应式。在 Vue.js 中&#xff0c;当数据对象的属性被直接修改时&#xff0c;Vue 可以监测到数据变化并响应变化。但若添加新的响应式对象属性时&am…...

Selenium 遇见伪元素该如何处理?

问题发生 在很多前端页面中&#xff0c;大家会见到很多&#xff1a;:before、::after 元素&#xff0c;比如【百度流量研究院】&#xff1a; 比如【百度疫情大数据平台】&#xff1a; 以【百度疫情大数据平台】为例&#xff0c;“累计确诊”文本并没有显示在 HTML 源代码中&am…...

RPA技术介绍与应用价值

一、什么是RPA技术? RPA(Robotic Process Automation)机器人流程自动化,是一种能够模拟人类来执行重复性任务的新型技术。RPA可实现统筹安排、自动化业务处理,并提升业务工作流处理效率。用户只需通过图形方式显示的计算机操作界面对RPA软件进行动态设定即可。借助RPA (R…...

产品经理,需要具备哪些能力和知识

作为产品经理&#xff0c;需要具备以下能力和知识&#xff1a; 产品管理能力&#xff1a;具备全面的产品管理能力&#xff0c;包括产品策划、需求分析、产品规划、产品设计、项目管理、市场调研和竞争分析等。 用户导向思维&#xff1a;能够理解用户需求和期望&#xff0c;以…...

【C++】map和set

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

crawlab通过docker单节点部署简单爬虫

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

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…...

基于单片机的宠物屋智能系统设计与实现(论文+源码)

本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢&#xff0c;连接红外测温传感器&#xff0c;可实时精准捕捉宠物体温变化&#xff0c;以便及时发现健康异常&#xff1b;水位检测传感器时刻监测饮用水余量&#xff0c;防止宠物…...