当前位置: 首页 > 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…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...