观察者模式的实现
引言:观察者模式——程序中的“通信兵”
在现代战争中,通信是胜利的关键。信息力以网络、数据、算法、算力等为底层支撑,在现代战争中不断推动感知、决策、指控等各环节产生量变与质变。在软件架构中,观察者模式扮演着类似的角色,它是确保信息在系统中高效、准确地流动的“通信兵”。
观察者模式确保了在软件系统中,当一个对象的状态发生变化时,所有依赖于这个状态的对象都能够及时得到通知。这种模式通过定义对象间的一对多依赖关系,使得一个对象的改变能够自动传播到其他对象。
观察者模式的概念
观察者模式是一种行为设计模式,它定义了对象间的一种一对多的依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式非常适合于实现分布式事件处理系统,如用户界面元素的响应、股票价格更新通知等。
为什么选择观察者模式?
-
降低耦合度:观察者模式通过定义对象间的依赖关系,降低了组件之间的耦合度,使得系统更加模块化。
-
提高系统的可扩展性:当需要增加新的观察者或被观察对象时,不需要修改现有的代码,只需遵循观察者模式的规则即可。
-
增强系统的灵活性:观察者模式允许对象在运行时动态地注册或注销观察者,使得系统能够灵活地响应变化。
本文的目的
在本文中,我们将深入探讨观察者模式的工作原理、实现方式以及如何在实际项目中应用它。
走近现实,聊聊军事下的“观察者模式”
观察者模式的角色构成
朱日和军演是中国每年举行的一次大规模军事演习,涉及多个部队和指挥中心。在这个例子中,我们可以将观察者模式应用到演习的指挥系统中。
主题(Subject):朱日和军演总指挥中心
- 总指挥中心负责制定演习计划,并维护一个观察者列表。
观察者(Observer):参演部队的指挥官或通信兵
- 参演部队的指挥官或通信兵希望在演习计划发生变化时能够收到通知。
具体主题(ConcreteSubject):具体的朱日和军演总指挥中心
- 具体的总指挥中心会在演习计划发生变化时通知所有观察者。
具体观察者(ConcreteObserver):具体的参演部队
- 具体的参演部队会在收到通知后,根据新的演习计划调整行动。
观察者模式的工作流程
-
注册: 各个参演部队向总指挥中心注册,表示自己希望收到演习计划的更新。
-
计划变更: 当总指挥中心制定了新的演习计划或现有计划发生变化时,计划变更被触发。
-
通知: 总指挥中心通知所有注册的参演部队,告知他们演习计划已经更新。
-
更新: 各个参演部队接收到通知后,根据新的演习计划调整自己的行动。
观察者模式的实现流程
下面,我将以朱日和军演的例子,将演习计划的变更通知到每一个参演部队,确保所有部队能够及时调整行动,协同作战。
第一步,新建一个主题接口,主要定义了注册、移除和通知观察者的方法。这是所有具体指挥中心必须实现的接口。
// 主题接口:军事指挥中心
public interface CommandCenter {// 注册观察者void registerObserver(Observer observer);// 移除观察者void removeObserver(Observer observer);// 通知所有注册的观察void notifyObservers(String exercisePlan);
}
第二步,新建一个观察者接口,其定义了一个更新方法,用于接收主题的通知。这是所有具体观察者必须实现的接口。
// 观察者:接收主题的通知
public interface Observer {void update(String message);
}
第三步,创建具体主题类,实现了 CommandCenter 接口,负责管理观察者列表,并在演习计划改变时通知所有观察者。
// 具体主题类:朱日和指挥中心
public class ZhuRiHeCommandCenter implements CommandCenter {private List<Observer> observers = new ArrayList<>();@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers(String exercisePlan) {observers.forEach(observer -> observer.update(exercisePlan));}// 改变演习计划并通知观察者public void changeExercisePlan(String newPlan) {notifyObservers(newPlan);}
}
第四步,新建了一个TroopCommander 类, 实现了Observer 接口,负责接收演习计划的更新,并通知其下属的部队。
// 具体观察者:团长
public class TroopCommander implements Observer {private String name;private List<Troop> troops;public TroopCommander(String name) {this.name = name;this.troops = new ArrayList<>();}public void addTroop(Troop troop) {troops.add(troop);}@Overridepublic void update(String exercisePlan) {System.out.println(name + "收到指挥中心的命令:" + exercisePlan + "。并通知全体部队开始执行计划!");for (Troop troop : troops) {troop.executePlan(exercisePlan);}}
}
第五步,再次创建一个观察者,定义执行计划的方法,用于执行具体的演习计划。
// 观察者:执行具体的演习计划
public interface Troop {void executePlan(String plan);
}
第六步,创建具体部队观察者,实现了 Troop 接口,负责执行具体的演习计划。
// 具体观察者:部队
public class CampTroop implements Troop {private String name;public CampTroop(String name) {this.name = name;}@Overridepublic void executePlan(String plan) {System.out.println(name + "收到!执行计划:" + plan);}
}
第七步,在客户端代码中使用观察者来执行朱日和军演指挥流程。
// 测试类
public class ZhuRiHeExerciseSystem {public static void main(String[] args) {ZhuRiHeCommandCenter commandCenter = new ZhuRiHeCommandCenter();TroopCommander reedCommander = new TroopCommander("红军");TroopCommander buleCommander = new TroopCommander("蓝军");reedCommander.addTroop(new CampTroop("一营"));reedCommander.addTroop(new CampTroop("二营"));buleCommander.addTroop(new CampTroop("三营"));buleCommander.addTroop(new CampTroop("四营"));commandCenter.registerObserver(reedCommander);commandCenter.changeExercisePlan("执行方案A");commandCenter.removeObserver(reedCommander);commandCenter.registerObserver(buleCommander);commandCenter.changeExercisePlan("执行方案B");}
}
从结果上看,利用观察者模式,红蓝双方都准备接收到了来自指挥中心传达的命令。
相关文章:
观察者模式的实现
引言:观察者模式——程序中的“通信兵” 在现代战争中,通信是胜利的关键。信息力以网络、数据、算法、算力等为底层支撑,在现代战争中不断推动感知、决策、指控等各环节产生量变与质变。在软件架构中,观察者模式扮演着类似的角色…...
Eureka: Netflix开源的服务发现框架
在微服务架构中,服务发现是一个关键组件,它允许服务实例之间相互发现并进行通信。Eureka是由Netflix开源的服务发现框架,它是Spring Cloud体系中的核心组件之一。Eureka提供了服务注册与发现的功能,支持区域感知和自我保护机制&am…...
go-基准测试
基准测试 Demo // fib_test.go package mainimport "testing"func BenchmarkFib(b *testing.B) {for n : 0; n < b.N; n {fib(30) // run fib(30) b.N times} }func fib(n int) int {if n 0 || n 1 {return n}return fib(n-2) fib(n-1) }benchmark 和普通的单…...
线性代数|机器学习-P23梯度下降
文章目录 1. 梯度下降[线搜索方法]1.1 线搜索方法,运用一阶导数信息1.2 经典牛顿方法,运用二阶导数信息 2. hessian矩阵和凸函数2.1 实对称矩阵函数求导2.2. 线性函数求导 3. 无约束条件下的最值问题4. 正则化4.1 定义4.2 性质 5. 回溯线性搜索法 1. 梯度…...
SQL,python,knime将数据混合的文字数字拆出来,合并计算实战
将下面将数据混合的文字数字拆出来,合并计算 一、SQL解决: ---创建表插入数据 CREATE TABLE original_data (id INT AUTO_INCREMENT PRIMARY KEY,city VARCHAR(255),value DECIMAL(10, 2) );INSERT INTO original_data (city, value) VALUES (上海0.5…...
mac ssh连接工具
在Mac上,有多个SSH连接工具可供选择,这些工具根据其功能和适用场景的不同,可以满足不同用户的需求。以下是一些推荐的SSH客户端软件:12 iTerm2:这是一款功能强大的终端应用程序,提供了丰富的功能和定制选项…...
阿里通义音频生成大模型 FunAudioLLM 开源
简介 近年来,人工智能(AI)技术的进步极大地改变了人类与机器的互动方式,特别是在语音处理领域。阿里巴巴通义实验室最近开源了一个名为FunAudioLLM的语音大模型项目,旨在促进人类与大型语言模型(LLMs&…...
通用详情页的打造
背景介绍 大家都知道,详情页承载了站内的核心流量。它的量级到底有多大呢? 我们来看一下,日均播放次数数亿次,这么大的流量,其重要程度可想而知。 在这样一个页面,每一个功能都是大量业务的汇总点。 作为…...
java内部类的本质
定义在类内部,可以实现对外部完全隐藏,可以有更好的封装性,代码实现上也往往更为简洁。 内部类可以方便地访问外部类的私有变量,可以声明为private从而实现对外完全隐藏。 在Java中,根据定义的位置和方式不同…...
vue3 学习笔记08 -- computed 和 watch
vue3 学习笔记08 – computed 和 watch computed computed 是 Vue 3 中用于创建计算属性的重要 API,它能够根据其它响应式数据动态计算出一个新的值,并确保在依赖数据变化时自动更新。 基本用法 squaredCount 是一个计算属性,它依赖于 count…...
Python-PLAXIS自动化建模技术与典型岩土工程案例
有限单元法在岩土工程问题中应用非常广泛,很多软件都采用有限单元解法。在使用各大软件进行数值模拟建模的过程中,岩土工程中的各种问题(塑性、渗流、固结、动力、稳定安全、热力TM),一步一步地搭建自己的Plaxis模型&a…...
license系统模型设计使用django models
User (用户)License (许可证)Product (产品)LicenseAssignment (许可证分配) 简单的模型定义: from django.db import models from django.contrib.auth.models import Userclass Product(models.Model):name models.CharField(max_length255)description model…...
【通信协议-RTCM】MSM语句(1) - 多信号GNSS观测数据消息格式
注释: RTCM响应消息1020为GLONASS星历信息,暂不介绍,前公司暂未研发RTCM消息类型版本的DR/RTK模块,DR/RTK模块仅NMEA消息类型使用 注释: 公司使用的多信号语句类型为MSM4&MSM7,也应该是运用最广泛的语句…...
vue3-vite-pinia模板
模板说明 下载 git clone https://github.com/AIxiaoHanBao/vue-template.gitmodule参数 node版本 16 UI组件库 element-plus 持久化 pinia 网络请求 axios 路由 vue-router 使用说明 权限管理目录access资源目录assets组件目录components页面目录pages网络请求目录re…...
华为HCIP Datacom H12-821 卷38
1.多选题 下面关于 BGP中的公认属性的描述,正确的是 A、公认必遵属性是所有BGP路由器都识别,且必须存在于Updata消息中心 B、BGP必须识别所有公认属性 C、公认属性分为公认必遵和可选过渡两种 D、公认任意属性是所有BGP造由器都可以识别,…...
C语言求10进制转2进制(除2取余法)
1.思路:除2取余法,也就是说用除以2取余来将10进制数转换为二进制 2.两种代码实现,这里用了两,一个递归一个非递归。 递归是一种编程技术,其中一个函数直接或间接地调用自己。递归通常用于解决那些可以被分解为更小的、…...
PHP 调用淘宝详情 API 接口的方法与实践
以下是关于“PHP 调用淘宝详情 API 接口的方法与实践”的一篇文章示例: PHP 调用淘宝详情 API 接口的方法与实践 在当今的电商时代,获取淘宝商品的详情信息对于许多开发者来说是一项重要的任务。使用 PHP 语言来调用淘宝详情 API 接口,可以…...
风景区服务热线系统:智能化时代的旅游新选择
一、引言 1 、风景区服务热线系统的概念 风景区服务热线系统是指为游客提供实时旅游信息咨询、投诉处理、紧急救援等一系列服务的电话和网络平台。它不仅是景区与游客之间的重要沟通桥梁,也是提升游客满意度、优化景区管理的重要手段。 2 、智能化时代对旅游服务…...
Linux修改配置文件后无法使用命令或无法进入桌面
如果你是修改了配置文件,如 sudo vim /etc/profile重启无数次发现无法进入桌面,不要着急重装系统!!,怎么造成的怎么改就行了 以下方案需要root密码,忘记密码详见:Linux忘记root密码怎么办 一…...
安卓14中Zygote初始化流程及源码分析
文章目录 日志抓取结合日志与源码分析systemServer zygote创建时序图一般应用 zygote 创建时序图向 zygote socket 发送数据时序图 本文首发地址 https://h89.cn/archives/298.html 最新更新地址 https://gitee.com/chenjim/chenjimblog 本文主要结合日志和代码看安卓 14 中 Zy…...
等保一体机 | 什么是等保一体机?一台机器就能过等保吗?
什么是等保一体机? 对于中小型企业来说,他们在接触到等保的条件下,可能会觉得成本太高了,毕竟整改的时候,几台安全设备下来报价就几十w。 也许有些人会听说过等保一体机 那么什么是等保一体机呢? 等保一…...
【活动预告】Apache IoTDB TsFile 智慧能源应用“上会”啦!
2024 年,站在中国数字经济产业升级和数据要素市场化建设的时代交汇点上,为进一步推动全球数据库产业进步,由中国通信标准化协会、大数据技术标准推进委员会主办的“2024 可信数据库发展大会”将于 2024 年 7 月 16-17 日,在北京朝…...
【公益案例展】中国电信安全大模型——锻造安全行业能量转化的高性能引擎...
电信安全公益案例 本项目案例由电信安全投递并参与数据猿与上海大数据联盟联合推出的 #榜样的力量# 《2024中国数智产业最具社会责任感企业》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 以GPT系列为代表的大模型技术,展现了人工智能技术与应…...
CV07_深度学习模块之间的缝合教学(2)--维度转换
教学(1):链接 1.1 预备知识 问题:假如说我们使用的模型张量是三维的,但是我们要缝合的模块是四维的,应该怎么办? 方法:pytorch中常用的函数:(1)view函数(2…...
Oracle字符集修改
提示 Oracle数据库默认的字符集编码为US7ASCII,这个编码是不支持中文的,如果想要在数据库存储中文,就需要修改编码为ZHS16GBK或UTF-8 编码和字符集是一个意思,只是叫法不一样而已 前置条件 修改字符集的前提是知道我们现在用的是什…...
k8s核心操作_k8s中的存储抽象_基本概念与NFS搭建_Deployment使用NFS进行挂载---分布式云原生部署架构搭建028
然后我们继续开始看 如果我们使用容器部署,比如我们有三个节点,一个是master,一个node1 一个是node2 那么pod 中我们可以看到,容器中的 /data 等各个目录都映射了出来了,但是 如果比如上面红色的部分,有个pod,原来在node2上,最右边那个,但是这个pod宕机了 那么,k8s会在node…...
数学建模·熵权法
熵权法 一种计算评价指标之间权重的方法。熵权法是一种客观的方法,没有主观性,比较可靠。 具体定义 熵权法的核心在于计算信息熵,信息熵反映了一个信息的紊乱程度,体现了信息的可靠性 具体步骤 Step1正向化处理 将所以评价指标转…...
开放开源开先河(一)
2022年7月28日,以“软件定义世界 开源共筑未来”为主题的全球数字经济大会开放原子开源峰会在北京开幕,承办主峰会和为捐赠人进行授牌仪式的开放原子开源基金会再次进入公众视野。基金会秘书长孙文龙从汇聚全球产业链开源力量、核心链接能力、开发者分享…...
美团收银Android一面凉经(2024)
美团收银Android一面凉经(2024) 笔者作为一名双非二本毕业7年老Android, 最近面试了不少公司, 目前已告一段落, 整理一下各家的面试问题, 打算陆续发布出来, 供有缘人参考。今天给大家带来的是《美团收银Android一面凉经(2024)》。 应聘岗位: 美团餐饮PaaS平台Android开发工程师…...
触发器练习
在product表上创建三个触发器。每次激活触发器后,都会更新operate表。product表和 表的内容如下 Product表内容 字段名 字段描述 数据类型 主键 外键 非空 唯一 自增 Id 产品编号 Int(10) 是 否 …...
哪个网站做网络推好/怎么在网上打广告
公共数据集推动了机器学习研究的飞速发展(h/t 吴恩达),但要将这些数据集导入机器学习管道,仍非易事。每个数据集的源格式和复杂性都不尽相同,编写一次性脚本,用于下载和准备所使用的数据集,这是每位研究人员都有过的切…...
wordpress简约HTML5/seo常见的优化技术
Java虚拟机(JVM)在执行Java程序的过程中会把它所管理的内存分为若干个不同的数据区域。包括程序计数器,Java虚拟机栈(栈),本地方法栈,Java堆,方法区,运行时常量池和直接内存。本文也介绍了各内存区域的异常抛出&#x…...
域名为www.com的网站/网站制作的费用
正则表达式模式修正符:i 忽略大小写m 多行视作一行g 全局匹配s .圆点匹配换行符,默认不包括换行x 空白字符除了被转义的或在字符类中的以外完全被忽略,在未转义的字符类之外的 # 以及下一个换行符之间的所有字符,包括两头,也都被忽略。e preg…...
销售网站平台怎么做的/手机百度搜索引擎入口
在 Windows 中,如果您想要监视 Python 程序是否接收到 WM_CLOSE 消息,可以使用 Python 的 win32api 模块和 win32gui 模块。这些模块提供了 Windows API 的 Python 绑定。 下面是一个简单的示例程序,该程序监视指定窗口句柄是否接收到 WM_CLO…...
聊城网站制作公司电话/苏州seo怎么做
1.重载操作符返回*this 2.返回类成员变量的引用,最好加const,不破坏类成员的封装性 如下:复制于 C 中引用有什么用? - 谢之易的回答 - 知乎 https://www.zhihu.com/question/34267829/answer/58414818 转载于:https://www.cnblogs…...
江门桂城网站建设/万能bt搜索引擎网站
安装版本 工作中经常使用 CentOS 7.6-1810 版本(推荐 CentOS-7-x86_64-Everything-1810.iso),开机后常常会设置一些基本配置,这里统一记录下来,方便后续环境部署简单化。 基本配置 #修改历史命令个数 sed -i s/^HIS…...