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

观察者模式的实现

引言:观察者模式——程序中的“通信兵”

在现代战争中,通信是胜利的关键。信息力以网络、数据、算法、算力等为底层支撑,在现代战争中不断推动感知、决策、指控等各环节产生量变与质变。在软件架构中,观察者模式扮演着类似的角色,它是确保信息在系统中高效、准确地流动的“通信兵”。
在这里插入图片描述

观察者模式确保了在软件系统中,当一个对象的状态发生变化时,所有依赖于这个状态的对象都能够及时得到通知。这种模式通过定义对象间的一对多依赖关系,使得一个对象的改变能够自动传播到其他对象。

观察者模式的概念

观察者模式是一种行为设计模式,它定义了对象间的一种一对多的依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式非常适合于实现分布式事件处理系统,如用户界面元素的响应、股票价格更新通知等。

为什么选择观察者模式?

  1. 降低耦合度:观察者模式通过定义对象间的依赖关系,降低了组件之间的耦合度,使得系统更加模块化。

  2. 提高系统的可扩展性:当需要增加新的观察者或被观察对象时,不需要修改现有的代码,只需遵循观察者模式的规则即可。

  3. 增强系统的灵活性:观察者模式允许对象在运行时动态地注册或注销观察者,使得系统能够灵活地响应变化。

本文的目的

在本文中,我们将深入探讨观察者模式的工作原理、实现方式以及如何在实际项目中应用它。

走近现实,聊聊军事下的“观察者模式”

观察者模式的角色构成

朱日和军演是中国每年举行的一次大规模军事演习,涉及多个部队和指挥中心。在这个例子中,我们可以将观察者模式应用到演习的指挥系统中。

主题(Subject):朱日和军演总指挥中心

  • 总指挥中心负责制定演习计划,并维护一个观察者列表。

观察者(Observer):参演部队的指挥官或通信兵

  • 参演部队的指挥官或通信兵希望在演习计划发生变化时能够收到通知。

具体主题(ConcreteSubject):具体的朱日和军演总指挥中心

  • 具体的总指挥中心会在演习计划发生变化时通知所有观察者。

具体观察者(ConcreteObserver):具体的参演部队

  • 具体的参演部队会在收到通知后,根据新的演习计划调整行动。

观察者模式的工作流程

  1. 注册: 各个参演部队向总指挥中心注册,表示自己希望收到演习计划的更新。

  2. 计划变更: 当总指挥中心制定了新的演习计划或现有计划发生变化时,计划变更被触发。

  3. 通知: 总指挥中心通知所有注册的参演部队,告知他们演习计划已经更新。

  4. 更新: 各个参演部队接收到通知后,根据新的演习计划调整自己的行动。

观察者模式的实现流程

下面,我将以朱日和军演的例子,将演习计划的变更通知到每一个参演部队,确保所有部队能够及时调整行动,协同作战。
在这里插入图片描述

第一步,新建一个主题接口,主要定义了注册、移除和通知观察者的方法。这是所有具体指挥中心必须实现的接口。

// 主题接口:军事指挥中心
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");}
}

从结果上看,利用观察者模式,红蓝双方都准备接收到了来自指挥中心传达的命令。
在这里插入图片描述

相关文章:

观察者模式的实现

引言&#xff1a;观察者模式——程序中的“通信兵” 在现代战争中&#xff0c;通信是胜利的关键。信息力以网络、数据、算法、算力等为底层支撑&#xff0c;在现代战争中不断推动感知、决策、指控等各环节产生量变与质变。在软件架构中&#xff0c;观察者模式扮演着类似的角色…...

Eureka: Netflix开源的服务发现框架

在微服务架构中&#xff0c;服务发现是一个关键组件&#xff0c;它允许服务实例之间相互发现并进行通信。Eureka是由Netflix开源的服务发现框架&#xff0c;它是Spring Cloud体系中的核心组件之一。Eureka提供了服务注册与发现的功能&#xff0c;支持区域感知和自我保护机制&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 线搜索方法&#xff0c;运用一阶导数信息1.2 经典牛顿方法&#xff0c;运用二阶导数信息 2. hessian矩阵和凸函数2.1 实对称矩阵函数求导2.2. 线性函数求导 3. 无约束条件下的最值问题4. 正则化4.1 定义4.2 性质 5. 回溯线性搜索法 1. 梯度…...

SQL,python,knime将数据混合的文字数字拆出来,合并计算实战

将下面将数据混合的文字数字拆出来&#xff0c;合并计算 一、SQL解决&#xff1a; ---创建表插入数据 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上&#xff0c;有多个SSH连接工具可供选择&#xff0c;这些工具根据其功能和适用场景的不同&#xff0c;可以满足不同用户的需求。以下是一些推荐的SSH客户端软件&#xff1a;12 iTerm2&#xff1a;这是一款功能强大的终端应用程序&#xff0c;提供了丰富的功能和定制选项…...

阿里通义音频生成大模型 FunAudioLLM 开源

简介 近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术的进步极大地改变了人类与机器的互动方式&#xff0c;特别是在语音处理领域。阿里巴巴通义实验室最近开源了一个名为FunAudioLLM的语音大模型项目&#xff0c;旨在促进人类与大型语言模型&#xff08;LLMs&…...

通用详情页的打造

背景介绍 大家都知道&#xff0c;详情页承载了站内的核心流量。它的量级到底有多大呢&#xff1f; 我们来看一下&#xff0c;日均播放次数数亿次&#xff0c;这么大的流量&#xff0c;其重要程度可想而知。 在这样一个页面&#xff0c;每一个功能都是大量业务的汇总点。 作为…...

java内部类的本质

定义在类内部&#xff0c;可以实现对外部完全隐藏&#xff0c;可以有更好的封装性&#xff0c;代码实现上也往往更为简洁。 内部类可以方便地访问外部类的私有变量&#xff0c;可以声明为private从而实现对外完全隐藏。 在Java中&#xff0c;根据定义的位置和方式不同&#xf…...

vue3 学习笔记08 -- computed 和 watch

vue3 学习笔记08 – computed 和 watch computed computed 是 Vue 3 中用于创建计算属性的重要 API&#xff0c;它能够根据其它响应式数据动态计算出一个新的值&#xff0c;并确保在依赖数据变化时自动更新。 基本用法 squaredCount 是一个计算属性&#xff0c;它依赖于 count…...

Python-PLAXIS自动化建模技术与典型岩土工程案例

有限单元法在岩土工程问题中应用非常广泛&#xff0c;很多软件都采用有限单元解法。在使用各大软件进行数值模拟建模的过程中&#xff0c;岩土工程中的各种问题&#xff08;塑性、渗流、固结、动力、稳定安全、热力TM&#xff09;&#xff0c;一步一步地搭建自己的Plaxis模型&a…...

license系统模型设计使用django models

User (用户)License (许可证)Product (产品)LicenseAssignment (许可证分配) 简单的模型定义&#xff1a; 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观测数据消息格式

注释&#xff1a; RTCM响应消息1020为GLONASS星历信息&#xff0c;暂不介绍&#xff0c;前公司暂未研发RTCM消息类型版本的DR/RTK模块&#xff0c;DR/RTK模块仅NMEA消息类型使用 注释&#xff1a; 公司使用的多信号语句类型为MSM4&MSM7&#xff0c;也应该是运用最广泛的语句…...

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中的公认属性的描述&#xff0c;正确的是 A、公认必遵属性是所有BGP路由器都识别&#xff0c;且必须存在于Updata消息中心 B、BGP必须识别所有公认属性 C、公认属性分为公认必遵和可选过渡两种 D、公认任意属性是所有BGP造由器都可以识别&#xff0c…...

C语言求10进制转2进制(除2取余法)

1.思路&#xff1a;除2取余法&#xff0c;也就是说用除以2取余来将10进制数转换为二进制 2.两种代码实现&#xff0c;这里用了两&#xff0c;一个递归一个非递归。 递归是一种编程技术&#xff0c;其中一个函数直接或间接地调用自己。递归通常用于解决那些可以被分解为更小的、…...

PHP 调用淘宝详情 API 接口的方法与实践

以下是关于“PHP 调用淘宝详情 API 接口的方法与实践”的一篇文章示例&#xff1a; PHP 调用淘宝详情 API 接口的方法与实践 在当今的电商时代&#xff0c;获取淘宝商品的详情信息对于许多开发者来说是一项重要的任务。使用 PHP 语言来调用淘宝详情 API 接口&#xff0c;可以…...

风景区服务热线系统:智能化时代的旅游新选择

一、引言 1 、风景区服务热线系统的概念 风景区服务热线系统是指为游客提供实时旅游信息咨询、投诉处理、紧急救援等一系列服务的电话和网络平台。它不仅是景区与游客之间的重要沟通桥梁&#xff0c;也是提升游客满意度、优化景区管理的重要手段。 2 、智能化时代对旅游服务…...

Linux修改配置文件后无法使用命令或无法进入桌面

如果你是修改了配置文件&#xff0c;如 sudo vim /etc/profile重启无数次发现无法进入桌面&#xff0c;不要着急重装系统&#xff01;&#xff01;&#xff0c;怎么造成的怎么改就行了 以下方案需要root密码&#xff0c;忘记密码详见&#xff1a;Linux忘记root密码怎么办 一…...

安卓14中Zygote初始化流程及源码分析

文章目录 日志抓取结合日志与源码分析systemServer zygote创建时序图一般应用 zygote 创建时序图向 zygote socket 发送数据时序图 本文首发地址 https://h89.cn/archives/298.html 最新更新地址 https://gitee.com/chenjim/chenjimblog 本文主要结合日志和代码看安卓 14 中 Zy…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...