笨蛋学设计模式行为型模式-观察者模式【14】
行为型模式-观察者模式
- 8.1观察者模式:arrow_up::arrow_up::arrow_up:
- 8.1.1概念
- 8.1.2场景
- 8.1.3优势 / 劣势
- 8.1.4观察者模式可分为
- 观察者的基本结构:
- 8.1.5观察者模式
- 8.1.6实战
- 8.1.6.1题目描述
- 8.1.6.2输入描述
- 8.1.6.3输出描述
- 8.1.6.4代码
- 8.1.7总结
8.1观察者模式⬆️⬆️⬆️
8.1.1概念
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,会通知所有依赖它的观察者对象,使它们都能够得到通知并且被自动更新
8.1.2场景
在我们生活中,用户可以在音乐播放平台关注多个歌手,而当有歌手发布新的歌曲时,可以将歌曲发布到音乐播放平台,而平台会将新的歌曲详细信息发送给关注该歌手的用户。而此时歌手就相当于是观察者模式的主题对象,每个关注的用户则是观察者模式中的观察者对象,通过该模式,用户可以很及时的听到歌手的新歌曲,而歌手也可以很轻松的通知用户新歌曲的发布。
8.1.3优势 / 劣势
- 灵活性:提供了灵活的观察者注册机制,可以随时添加或删除观察者,使得系统更加灵活和可扩展
- 自动更新:当被观察者的状态发生改变时,所有依赖它的观察者都会自动收到通知并更新,提高了系统的自动化程度
- 性能影响:当被观察者的状态发生改变时,所有观察者都会收到通知并且进行相应的通知,可能导致大量的通知和计算,影响系统性能
- 通知竞态条件:若多个线程同时修改被观察者的状态,可能会产生竞态条件,导致某些观察者未能及时收到通知或收到错误的通知
8.1.4观察者模式可分为
- 主题Subject:就是被观察的对象,可以维护一组观察者,当主题本身发生改变时就会通知观察者
- 观察者Observer:观察主题的对象,当"被观察"的主题发生变化时,观察者就会得到通知并执行相应的处理
观察者的基本结构:
- 主题Subject:一般会定义成一个接口,提供方法用于注册、删除、通知观察者,通常也包含一个状态,当状态发生改变时,通知所有的观察者
- 观察者Observer:观察者也需要实现一个接口,包含一个更新方法,在接收主题通知时执行对应的操作
- 具体主题ConcreteSubject:主题的具体实现,维护一个观察者列表,包含了观察者的注册、删除、通知方法
- 具体观察者ConcreteObserver:观察者接口的具体实现,每个具体
8.1.5观察者模式
package com.technologystatck.designpattern.mode.observer;import java.util.ArrayList;
import java.util.List;public class Observers {public static void main(String[] args) {//创建具体主题对象ConcreteSubject concreteSubject = new ConcreteSubject();//创建具体观察者对象Observer concreteObserverA = new ConcreteObserver();Observer concreteObserverB = new ConcreteObserver();//注册观察者concreteSubject.registerObserver(concreteObserverA);concreteSubject.registerObserver(concreteObserverB);//调用主题方法concreteSubject.setState("有新的观察者注册");}
}//主题接口(主题)
interface Subject{//注册观察者void registerObserver(Observer observer);//移除观察者void removeObserver(Observer observer);//通知观察者void notifyObserver();
}//观察者接口(观察者)
interface Observer{//更新方法void update(String message);
}//具体主题实现
class ConcreteSubject implements Subject{//观察者列表private List<Observer> observers = new ArrayList<>();//状态private String state;//注册观察者方法(注册)@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}//移除观察者方法(移除)@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}//通知观察者方法(通知)//遍历观察者列表,并通知每个观察者更新状态@Overridepublic void notifyObserver() {for (Observer observer : observers) {observer.update(state);}}//更新状态public void setState(String state) {this.state = state;notifyObserver();}
}
//具体观察者实现
class ConcreteObserver implements Observer{//更新方法@Overridepublic void update(String message) {System.out.println(message);}
}
8.1.6实战
8.1.6.1题目描述
小明所在的学校有一个时钟(主题),每到整点时,它就会通知所有的学生(观察者)当前的时间,请你使用观察者模式实现这个时钟通知系统。
注意点:时间从 0 开始,并每隔一个小时更新一次。
8.1.6.2输入描述
输入的第一行是一个整数 N(1 ≤ N ≤ 20),表示学生的数量。
接下来的 N 行,每行包含一个字符串,表示学生的姓名。
最后一行是一个整数,表示时钟更新的次数。
8.1.6.3输出描述
对于每一次时钟更新,输出每个学生的姓名和当前的时间。
8.1.6.4代码
package com.technologystatck.designpattern.mode.observer;import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 读取学⽣数量int N = scanner.nextInt();// 创建时钟Clock clock = new Clock();// 注册学⽣观察者for (int i = 0; i < N; i++) {String studentName = scanner.next();clock.registerObserver(new Student(studentName));}// 读取时钟更新次数int updates = scanner.nextInt();// 模拟时钟每隔⼀个⼩时更新⼀次for (int i = 0; i < updates; i++) {clock.tick();}}
}// 观察者接⼝
interface Observer {void update(int hour);
}
// 主题接⼝
interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}
// 具体主题实现
class Clock implements Subject {private List<Observer> observers = new ArrayList<>();private int hour = 0;@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(hour);}}public void tick() {hour = (hour + 1) % 24; // 模拟时间的推移notifyObservers();}
}
// 具体观察者实现
class Student implements Observer {private String name;public Student(String name) {this.name = name;}@Overridepublic void update(int hour) {System.out.println(name + " " + hour);}
}
8.1.7总结
- 优点:可以灵活的增加 / 删除观察者对象,而不影响其他相关对象的功能
- 总结:定义一对多的依赖关系,让多个观察者对象同时监听某一主题对象的状态变化,实现自动更新
- 场景:适用于一个对象的状态变化会影响到其他对象,并且希望这些对象在状态变化时能够自动更新的情况
相关文章:
笨蛋学设计模式行为型模式-观察者模式【14】
行为型模式-观察者模式 8.1观察者模式:arrow_up::arrow_up::arrow_up:8.1.1概念8.1.2场景8.1.3优势 / 劣势8.1.4观察者模式可分为观察者的基本结构: 8.1.5观察者模式8.1.6实战8.1.6.1题目描述8.1.6.2输入描述8.1.6.3输出描述8.1.6.4代码 8.1.7总结 8.1观察者模式⬆️…...
上海智慧岛大数据云计算中心项目正式封顶!
上海智慧岛大数据云计算中心封顶仪式现场 1月15日,云端股份在上海智慧岛大数据云计算中心举行封顶仪式。云之端网络(江苏)股份有限公司(以下称“云端股份”)总经理贡伟力先生,常务副总张靖先生等公司成员&…...
靶场实战(19):OSCP备考之VulnHub HA WORDY
交流技术可以关注公众号 OneMoreThink 或后台添加微信,欢迎提出宝贵建议。 0、总结 0.1、攻击思路 资产发现 主机发现服务发现漏洞发现(获取权限) 80端口/HTTP服务 组件漏洞URL漏洞:RFI、FileUpload提升权限 www-data用户 sudosui…...
大模型学习与实践笔记(九)
一、LMDeply方式部署 使用 LMDeploy 以本地对话方式部署 InternLM-Chat-7B 模型,生成 300 字的小故事 2.api 方式部署 运行 结果: 显存占用: 二、报错与解决方案 在使用命令,对lmdeploy 进行源码安装是时,报错 1.源…...
fpga目前就业形势咋样?
FPGA今年各厂给本科生的薪资大概是15-30K,研究生是20-40K,平均薪资在25k左右, 当然具体薪资还要看去哪个公司,哪个城市,以及个人的学校、专业、能力水平、及包括面试时的表现,运气等,这些都会导…...
Linux7 安装 Oracle 19C RAC 详细图文教程
实战篇:Linux7 安装 Oracle 19C RAC 详细图文教程 本文是按照:https://www.modb.pro/db/154424的思路进行编写 一、安装前规划 安装RAC前,当然要先做好规划。具体包含以下几方面: 节点主机版本主机名实例名Grid/Oracle版本Publi…...
【SpringBoot】SpringBoot 项目初始化方法
github 搜索 springboot 模板 github 搜索 springboot 模板,拉取现成代码。 SpringBoot 官方的模板生成器 SpringBoot 官方的模板生成器(https://start.spring.io/) 在 IDEA 开发工具中生成 这里我修改成阿里的镜像主要是要使用 Java8。 …...
34. 在排序数组中查找元素的第一个和最后一个位置(二分查找)
二分查找到目标值然后左右找到坐标 问题在于:找左右坐标的时候时间复杂度不是O(logN) class Solution {public int[] searchRange(int[] nums, int target) {int[] ans {-1, -1};if (nums.length 0) return ans;int l 0, r nums.length;while (l < r) {int…...
Mysql深度分页优化的一个实践
问题简述: 最近在工作中遇到了大数据量的查询场景, 日产100w左右明细, 会查询近90天内的数据, 总数据量约1亿, 业务要求支持分页查询与导出. 无论是分页或导出都涉及到深度分页查询, mysql通过limit/offset实现的深度分页查询会存在全表扫描的问题, 比如offset1000w, limit10…...
【JavaEE进阶】 SpringBoot配置⽂件
文章目录 🍀配置⽂件的作⽤🌴SpringBoot配置⽂件🎋配置⽂件的格式🎄properties配置⽂件🚩properties基本语法🚩读取配置⽂件🚩properties的缺点 🌳yml配置⽂件yml基本语法Ƕ…...
excel 常用函数
求和函数: SUM: 将单个值、单元格引用或区域相加。 案例:SUM(A1:A5) (结果:A1到A5单元格的值求和) SUMIF: 对选中范围内符合指定条件的值求和。 案例:SUMIF(B1:B5, ">50&qu…...
【React基础】– JSX语法
文章目录 认识JSX为什么React选择了JSXJSX的使用 React事件绑定this的绑定问题事件参数传递 React条件渲染React列表渲染列表中的key JSX的本质createElement源码Babel官网查看直接编写jsx代码 虚拟DOM的创建过程jsx – 虚拟DOM – 真实DOM声明式编程 阶段案例练习 认识JSX ◼ …...
SpringBoot 项目中后端实现跨域的5种方式!!!
文章目录 SpringBoot 项目中后端实现跨域的5种方式!!!一、为什么会出现跨域问题二、什么是跨域三、非同源限制四、Java后端 实现 CORS 跨域请求的方式1、返回新的 CorsFilter(全局跨域)2、重写 WebMvcConfigurer(全局跨域)3、使用注解 (局部跨…...
Vue3前端开发,provide和enject的基础练习,跨层级传递数据
Vue3前端开发,provide和enject的基础练习,跨层级传递数据! 声明:provide虽然可以跨层级传递,但是依旧是需要由上向下的方向传递。根传子的方向。 <script setup> import {onMounted, ref} from vue import Base from ./components/Base.vue impor…...
Python 循环结构值while循环
while循环是一种常用的循环结构,它会在满足特定条件的情况下重复执行一段代码块。 基本语法: while condition:# 循环体代码while循环的执行过程如下: 首先,判断循环条件condition(布尔表达式)是否为真。…...
MSSQL-识别扩展extended event(扩展事件)中的时间单位
经常使用sqlserver extended event(扩展事件),但是总是忘记扩展事件使用的时间单位,不确定它们是 秒、毫秒、还是微秒? 以下下代码能够从 相关DMV中提取description字段内容来识别时间单位: SELECT [p].[name] [package_name],[o…...
vue3中l和vue2中v-model不同点
vue2比较让人诟病的一点就是提供了两种双向绑定:v-model和.sync, 在vue3中,去掉了.sync修饰符,只需要使用v-model进行双向绑定即可。 为了让v-model更好的针对多个属性进行双向绑定(vue2中自定义组件中v-model只能使用…...
使用 Swift 代码优化项目编译速度
引言 软件的性能是评价一个软件质量的重要指标,尤其在今天这个时代,性能已成为大型项目不可或缺的考虑因素之一。对于用户量极大的软件,如网银系统、在线购物商城等,更是必须保证其高效稳定的性能。在这种背景下,优化…...
基于springboot+vue的社区团购系统(前后端分离)
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…...
three.js从入门到精通系列教程002 - three.js正交相机OrthographicCamera
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>three.js从入门到精通系列教程002 - three.js正交相机OrthographicCamera</title><script src"ThreeJS/three.js"></script><script src&qu…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
