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

从一个小故事讲解观察者模式~

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

什么是观察者模式?

观察者模式在我们的日常生活中极其常见。

先来看看观察者模式的定义:

观察者模式定义了对象之间一对多的依赖,当这样一来,当一个对象状态改变时,它的所有依赖者都会收到通知并自动更新

这个模式在我们日常生活中可以说是太常见了!

比如手机上的天气预报,一旦气象局的信息进行了更新,手机上的天气信息就会相应的变化;

比如10086群发的消息,其实也是一个观察者模式的例子,每当10086发送一条消息时,所有的移动手机都会收到这个消息。而且一般消息中都会附带一个提醒“退订请回复T”,一旦回复了T,以后就不会接收到显10086对应的短信了

比如麦当劳吃炸鸡时,当一份食物准备好,就会通知“3045、3045、3045”请取餐,大家都能听到,但是可能只有一个人会去取餐,因为订阅者可以自行决定接收到消息之后动不动,或者说做什么;又比如…

观察者模式描述的就是订阅者和发布者之间的联系。其UML类图如下:

在这个下面给出订阅者和发布者的一个例子。

应用实例

借鉴《大话设计模式》的看门放哨的例子,我们来设计这样一个场景:

“一堂自习课时,小红、小蓝、小绿三人无心学习,各玩各的。坐在门口小黄在门口放哨,一旦看到班主任的身影,就敲一下桌子,其他三人应声而动,赶忙拿出书进行学习。当班主任走远了,小黄敲两下桌子,大家又开始愉快的玩耍…”

  • 主体接口

主体接口,又称为被观察者,采用接口的方式可以给具体的主体类实现自己的逻辑,如采用链表、数组、或者Map等结构存储观察者。

public interface Subject {// 增加观察者public void attach(Observer observer);// 删除观察者public void detach(Observer observer);// 通知所有观察者public void notifyObservers();// 主体(被观察者)状态public void setAction(String action);public String getAction();
}
  • 通知者接口

通知者接口主要是定义了一个接口,不同的通知者实现自己的消息逻辑:

public abstract class Observer {protected String name;protected Subject subject;public Observer(String name, Subject subject) {this.name = name;this.subject = subject;}public abstract void update();
}
  • 实际观察者(小红、小蓝、小绿)

分别实现三个同学:

public class Xiaohong extends Observer {public Xiaohong(String name, Subject subject) {super(name, subject);}@Overridepublic void update() {System.out.println(subject.getAction() + "\n" + name + "把小说藏起来!继续学习!");}
}
public class Xiaolan extends Observer {public Xiaolan(String name, Subject subject) {super(name, subject);}@Overridepublic void update() {System.out.println(subject.getAction() + "\n" + name + "把手机收起来!继续学习!");}
}
public class Xiaolv extends Observer {public Xiaolv(String name, Subject subject) {super(name, subject);}@Overridepublic void update() {System.out.println(subject.getAction() + "\n" + name + "把游戏机收起来!继续学习!");}
}
  • 实际发布者(小黄)

小黄观察老师的到来,通知大家:

public class Xiaohuang implements Subject {// 需要通知的同学列表private final List<Observer> observers = new LinkedList<>();private String action;// 添加通知同学@Overridepublic void attach(Observer observer) {observers.add(observer);}// 删除通知同学@Overridepublic void detach(Observer observer) {observers.remove(observer);}// 通知所有同学@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update();}}// 获取通知状态@Overridepublic String getAction() {return action;}// 设置通知状态@Overridepublic void setAction(String action) {this.action = action;}
}
  • 运行客户端
public class App {public static void main(String[] args) {// 前台为通知者Xiaohuang xiaohuang = new Xiaohuang();Xiaohong observer1 = new Xiaohong("小红", xiaohuang);Xiaolv observer2 = new Xiaolv("小绿", xiaohuang);Xiaolan observer3 = new Xiaolan("小蓝", xiaohuang);// 需要通知三个xiaohuang.attach(observer1);xiaohuang.attach(observer2);xiaohuang.attach(observer3);// 设置通知状态xiaohuang.setAction("小心!Boss回来了!");// 发送通知xiaohuang.notifyObservers();}
}

结果如下:

总结

优点

  • 观察者模式实现了发布者和订阅者之间的松耦合:两个对象之间可以进行交互,但是不太清楚彼此之间的细节;
  • 适用于一个对象改变,相联系的对象随之发生相应变化的场景

缺点

  • 如果对象之间有循环依赖,在观察者模式下可能会引发循环调用,从而造成系统崩溃;

总而言之,当对象之间的关系类似与消息群发这样的一对多关系时,就可以开始考虑用不用观察者模式了。(都这个时候了,不用它还能用谁啊?)

参考资料

《Head First 设计模式》

《大话设计模式》

观察者模式——极客教程

相关文章:

从一个小故事讲解观察者模式~

定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。 什么是观察者模式&#xff1f; 观察者模式在我们的日常生活中极其常见。 先来看看观察者模式的定义&#xff1a; 观察者模式定义了对象之间…...

LeetCode、1137. 第 N 个泰波那契数【简单,动态规划】

文章目录 前言LeetCode、1137. 第 N 个泰波那契数【简单&#xff0c;动态规划】题目与分类思路一维动态规划 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术…...

Python爬虫urllib详解

前言 学习爬虫&#xff0c;最初的操作便是模拟浏览器向服务器发出请求&#xff0c;那么我们需要从哪个地方做起呢&#xff1f;请求需要我们自己来构造吗&#xff1f;需要关心请求这个数据结构的实现吗&#xff1f;需要了解 HTTP、TCP、IP 层的网络传输通信吗&#xff1f;需要知…...

Linux嵌入式开发+驱动开发-中断

swi汇编指令可以产生软中断&#xff0c;以下是硬件中断的产生到执行完毕的全过程&#xff1a; 在自己设计的芯片“CPU响应中断”程序的第四个步骤可以转向“中断向量控制器”&#xff0c;中断向量控制器中存储中断元服务地址即处理中断处理程序的地址&#xff0c;而不用使用0X1…...

android tv开发-1,leanback

目录 1.leanback库的一些事 2.leanback在使用时遇到的一些麻烦 视频卡片 页面空白 关于左侧菜单的一些设置 数据加载异常与加载中的一些操作 如果页面无数据,如何显示错误的页面....

chisel RegInit/UInt/U

val reg RegInit(0.U(8.W)) //ok val reg RegInit(0.UInt(8.W)) //errU 使用在数字 . 后边50.U UInt 使用在IO(new Bundle val a Input(UInt(8.W)) 或者 def counter(max:UInt, a1:UInt) package emptyimport chisel3._ import chisel3.util._class MyCounter extends …...

华为OD机试真题-田忌赛马-2024年OD统一考试(C卷)

题目: 给定两个只包含数字的数组a,b,调整数组 a 里面数字的顺序,使得尽可能多的 a[i] >b[i]。数组 a和 b 中的数字各不相同。 输出所有可以达到最优结果的 a 数组的数量 输入描述: 输入的第一行是数组 a 中的数字,其中只包含数字,每两个数字之间相隔一个空格,a 数组…...

QMUI_Android:提升Android开发效率与质量的利器

QMUI_Android&#xff1a;提升Android开发效率与质量的利器 在Android应用开发过程中&#xff0c;开发者常常面临着重复编写基础组件和处理兼容性问题的挑战&#xff0c;这不仅耗费时间&#xff0c;也降低了开发效率。为了解决这一问题&#xff0c;Tencent推出了QMUI_Android框…...

如何部署Linux AMH服务器管理面板并结合内网穿透远程访问

文章目录 1. Linux 安装AMH 面板2. 本地访问AMH 面板3. Linux安装Cpolar4. 配置AMH面板公网地址5. 远程访问AMH面板6. 固定AMH面板公网地址 AMH 是一款基于 Linux 系统的服务器管理面板&#xff0c;它提供了一系列的功能&#xff0c;包括网站管理、FTP 管理、数据库管理、DNS 管…...

C++文件操作(2)

文件操作&#xff08;2&#xff09; 1.二进制模式读取文本文件2.使用二进制读写其他类型内容3.fstream类4.文件的随机存取文件指针的获取文件指针的移动 1.二进制模式读取文本文件 用二进制方式打开文本存储的文件时&#xff0c;也可以读取其中的内容&#xff0c;因为文本文件…...

Bootstrap5 图片轮播

Bootstrap5 轮播样式表使用的是CDN资源 <title>亚丁号</title><!-- 自定义样式表 --><link href"static/front/css/front.css" rel"stylesheet" /><!-- 新 Bootstrap5 核心 CSS 文件 --><link rel"stylesheet"…...

WINDOWS搭建NFS服务器

下载并安装 Networking Software for Windows 启动配置 找到安装目录&#xff08;如C:\Program Files\nfsd&#xff09;&#xff0c;双击nfsctl.exe&#xff0c;菜单Edit->Preferences 启动后&#xff1a; 配置Export Exports->Edit exports file 其他的几句我都删除…...

LeetCode、216. 组合总和 III【中等,组合型枚举】

文章目录 前言LeetCode、216. 组合总和 III【中等&#xff0c;组合型枚举】题目类型与分类思路 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖…...

支持534种语言,开源大语言模型MaLA-500

无论是开源的LLaMA 2还是闭源的GPT系列模型&#xff0c;功能虽然很强大&#xff0c;但对语言的支持和扩展比较差&#xff0c;例如&#xff0c;二者都是以英语为主的大模型。 为了提升大模型语言的多元化&#xff0c;慕尼黑大学、赫尔辛基大学等研究人员联合开源了&#xff0c;…...

面试 JavaScript 框架八股文十问十答第一期

面试 JavaScript 框架八股文十问十答第一期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01;关注专栏后就能收到持续更新&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1&#xff09;JavaScript有哪些…...

【发票识别】新增针对图片发票的识别(升级中)

说明 为了完善发票识别的功能&#xff0c;目前发票识别支持发票图片格式的识别&#xff0c;增加可用性。 体验 体验地址&#xff1a;https://invoice.behappyto.cn/invoice-service/ 体验地址上面有示例的发票&#xff0c;可以下载上传识别或者复制url地址进行识别。 技术栈…...

面试数据结构与算法总结分类+leetcode目录【基础版】

&#x1f9e1;&#x1f9e1;&#x1f9e1;算法题目总结&#xff1a; 这里为大家总结数据结构与算法的题库目录&#xff0c;如果已经解释过的题目会标注链接更新&#xff0c;方便查看。 数据结构概览 Array & String 大家对这两类肯定比较清楚的&#xff0c;同时这也是面试…...

音频二维码怎么制作出来的?支持多种格式音频生码的方法

怎么把一个音频的文件做成二维码图片呢&#xff1f;在日常工作和生活中&#xff0c;有很多的场景会需要使用音频类型的文件来展示内容&#xff0c;比如常见的英语听力、课程、听书等类型的内容&#xff0c;现在都可以用二维码展示。而且现在生成音频二维码的方法也很简单&#…...

ReactNative实现一个圆环进度条

我们直接看效果&#xff0c;如下图 我们在直接上代码 /*** 圆形进度条*/ import React, {useState, useEffect} from react; import Svg, {Circle,G,LinearGradient,Stop,Defs,Text, } from react-native-svg; import {View, StyleSheet} from react-native;// 渐变色 const C…...

【JS逆向学习】今日头条

逆向目标 目标网页&#xff1a;https://www.toutiao.com/?wid1707099375036目标接口&#xff1a;https://www.toutiao.com/api/pc/list/feed目标参数&#xff1a;_signature 逆向过程 老规矩先观察网络请求&#xff0c;过滤XHR请求观察加密参数&#xff0c;发现Payload的_s…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...