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

.NET 设计模式—观察者模式(Observer Pattern)

简介

在.NET中,观察者模式是一种设计模式,它允许对象之间进行一对多的依赖关系。当一个对象的状态发生变化时,所有依赖于它的对象都会收到通知并自动更新。这种模式在事件驱动的设计中非常常见。

在.NET中实现观察者模式,通常涉及到定义一个抽象的观察者接口和一个可被观察的对象。这个可被观察的对象维护一个观察者的列表,并在状态改变时通知所有观察者。

角色

  • 抽象主题角色(Subject):抽象主题把所有观察者对象的引用保存在一个列表中,并提供增加和删除观察者对象的操作,抽象主题角色又叫做抽象被观察者角色,一般由抽象类或接口实现。
  • 抽象观察者角色(Observer):为所有具体观察者定义一个接口,在得到主题通知时更新自己,一般由抽象类或接口实现。
  • 具体主题角色(ConcreteSubject):实现抽象主题接口,具体主题角色又叫做具体被观察者角色。
  • 具体观察者角色(ConcreteObserver):实现抽象观察者角色所要求的接口,以便使自身状态与主题的状态相协调。

优点

  • 观察者模式实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层,即观察者。
  • 观察者模式在被观察者和观察者之间建立了一个抽象的耦合,被观察者并不知道任何一个具体的观察者,只是保存着抽象观察者的列表,每个具体观察者都符合一个抽象观察者的接口。
  • 观察者模式支持广播通信。被观察者会向所有的注册过的观察者发出通知。

缺点

  • 如果一个被观察者有很多直接和间接的观察者时,将所有的观察者都通知到会花费很多时间。
  • 虽然观察者模式可以随时使观察者知道所观察的对象发送了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎样发生变化的。
  • 如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃,在使用观察者模式应特别注意这点。

应用场景

  • 当需要将一个对象的状态变化通知给其他多个对象时,可以使用观察者模式;
  • 当一个对象的改变需要同时改变其他对象的状态或者操作时,可以使用观察者模式;
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面时,可以使用观察者模式。例如,模型和视图之间的关系,模型驱动视图的更新,而视图反过来也要反映到模型中;
  • 当一个对象必须通知其他对象,但是你不知道这些对象是谁时,可以使用观察者模式。例如,你不知道哪些用户订阅了你的微信公众号,但你需要在每次发布新文章时通知所有订阅用户;
  • 当一个对象需要有别的对象来协助完成某项工作,并且不希望知道具体协助它的对象时,可以使用观察者模式。例如,一个员工完成某项任务需要得到经理的批准,但他并不知道具体是哪个经理会批准。

实现

  • 定义观察者接口
public interface IObserver
{void Update(string message); // 或者根据具体需求定义其他方法
}
  • 定义可观察的对象,它包含一个观察者列表,并提供注册和通知观察者的方法
using System.Collections.Generic;public class Observable
{private List<IObserver> observers = new List<IObserver>();private string state;// 注册观察者public void RegisterObserver(IObserver observer){observers.Add(observer);}// 移除观察者(可选)public void RemoveObserver(IObserver observer){observers.Remove(observer);}// 通知所有观察者(状态改变时调用)protected void NotifyObservers(string message){foreach (var observer in observers){observer.Update(message);}}// 改变状态并通知观察者(这里假设状态是一个字符串)public void ChangeState(string newState){state = newState;NotifyObservers("State changed to: " + state); // 通知所有观察者状态已改变及新状态信息}
}
  • 实现具体的观察者类,它实现观察者接口并定义如何响应通知
public class ConcreteObserver : IObserver
{public void Update(string message){// 在这里处理接收到的通知,比如更新UI、记录日志等操作。Console.WriteLine("Observer received: " + message); // 仅作为示例,实际实现根据需求来定。}
}
  • 上层应用调用
class Program
{static void Main(string[] args){// 创建可观察对象和观察者实例。Observable observable = new Observable();ConcreteObserver observer = new ConcreteObserver(); // 可以创建多个观察者实例。observable.RegisterObserver(observer); // 注册观察者到可观察对象。// ... 在程序的其他部分,当需要通知观察者时调用可观察对象的ChangeState方法     observable.ChangeState("New state information");。这样就会触发通知所有注册的观察者。}
}

相关文章:

.NET 设计模式—观察者模式(Observer Pattern)

简介 在.NET中&#xff0c;观察者模式是一种设计模式&#xff0c;它允许对象之间进行一对多的依赖关系。当一个对象的状态发生变化时&#xff0c;所有依赖于它的对象都会收到通知并自动更新。这种模式在事件驱动的设计中非常常见。 在.NET中实现观察者模式&#xff0c;通常涉…...

EasyUI Jquery 学习笔记 ——DataGrid(数据网格)与 Tree(树)详细版

1. DataGrid(数据网格)与 Tree(树) 1.1 Datagrid 数据网格 扩展自 $.fn.panel.defaults。通过 $.fn.datagrid.defaults 重写默认的 defaults。 数据网格(datagrid)以表格格式显示数据,并为选择、排序、分组和编辑数据提供了丰富的支持。数据网格(datagrid)的设计目…...

JAVA发票验真接口、票据ocr、数电票在线查验真伪

发票验真接口&#xff0c;,实时联网核验发票真伪,查验一致返回全票面信息&#xff0c;支持查验增值税发票管理系统开具的发票,支持批量核验发票&#xff0c;翔云发票查验送发票识别,助您摆脱手动输入繁琐,提升工作效率。 发票查验接口适用于银行、金融、代理记账等发票管理数量…...

el-date-picker调用回车事件

elementui的el-date-picker想要调用回车事件&#xff1a; <el-date-pickerv-model"state.date"type"date"value-format"YYYY-MM-DD HH:mm:ss"placeholder"选择日期"clearablekeydown.enter"handleDown"></el-date-…...

js学习总结

这里写目录标题 前情提要JavaScript书写位置1. 内部javaScript (不常用)2. 外部javaScript (常用)3.内联javaScript (常用) js中的输入和输出输出语法1. document.write()2. alert()3. console.log() 输入语法prompt() 前情提要 1. 在javaScript中的 分号 是可以省略的JavaScr…...

MES实施优势有哪些?MES制造执行系统的主要内容

各个行业之间也开始进入到了激烈的竞争当中&#xff0c;很多企业为了能够有效提升企业竞争力&#xff0c;都会通过提升自身实力的方式来提升竞争力。一些制造业也会在经营过程当中使用到MES系统&#xff0c;那么&#xff0c;mes系统的优势有哪些呢&#xff1f; 1、优化企业现场…...

ChatGPT 和 Elasticsearch:使用 Elastic 数据创建自定义 GPT

作者&#xff1a;Sandra Gonzales ChatGPT Plus 订阅者现在有机会创建他们自己的定制版 ChatGPT&#xff0c;称为 GPT&#xff0c;这替代了之前博客文章中讨论的插件。基于本系列的第一部分的基础 —— 我们深入探讨了在 Elastic Cloud 中设置 Elasticsearch 数据和创建向量嵌…...

废品回收 小程序+APP

用户实名认证、回收员实名认证、后台审核、会员管理、回收员管理、订单管理、提现管理、地图、档案管理。 支持&#xff0c;安卓APP、苹果APP、小程序 流程&#xff1a; 一、用户端下单&#xff0c;地图选择上门位置、填写具体位置、废品名称、预估重量、选择是企业废旧、家…...

下载好了annaconda,但是在创建一个新的Conda虚拟环境报错

文章目录 问题描述&#xff1a;解决方案1.生成一个配置文件 问题总结 问题描述&#xff1a; ProxyError(MaxRetryError(“HTTPSConnectionPool(host‘repo.anaconda.com’, port443): Max retries exceeded with url: /pkgs/pro/win-64/repodata.json.bz2 (Caused by ProxyErr…...

如何安装MacOS的虚拟机?mac安装虚拟机的步骤 虚拟机安装MacOS VMware Fusion和Parallels Desktop19

要在Mac上运行MacOS的虚拟机&#xff0c;常用的方法是使用虚拟化软件如VMware Fusion或Parallels Desktop。 以下是安装MacOS的虚拟机的主要步骤&#xff1a; 1. 检查系统要求&#xff1a;确定您的Mac硬件和操作系统满足安装要求。您需要一台具备足够性能的Mac&#xff0c;并…...

Flutter 中 AutomaticKeepAliveClientMixin 的介绍及使用

在 Flutter 中&#xff0c;当你在一个页面中滑动列表或者进行其他一些操作时&#xff0c;如果你返回到该页面&#xff0c;可能会发现之前的状态已经丢失了。这在某些情况下可能是不可取的&#xff0c;特别是当你想要保留之前的状态&#xff0c;而不是每次都重新加载页面时。 为…...

注意力机制篇 | YOLOv8改进之清华开源ACmix:自注意力和CNN的融合 | 性能速度全面提升

前言:Hello大家好,我是小哥谈。混合模型ACmix将自注意力机制和卷积神经网络进行整合,使其同时具有自注意力机制和卷积神经网络的优点。这是清华大学、华为和北京人工智能研究院共同发布在2022年CVPR中的论文。ACmix结合了自注意力机制和卷积神经网络的优势,以提高模型的性能…...

Go语言支持重载吗?如何实现重写?

Go语言不支持传统意义上的函数和方法重载。在Go语言中&#xff0c;函数名或方法名不能相同但参数列表不同&#xff0c;因为这会导致编译错误。 然而&#xff0c;可以通过方法重写&#xff08;override&#xff09;来实现类似的功能。方法重写是指在子类中定义一个与父类同名的…...

Spring中基于事件监听驱动 和 线程池的异步任务

文章目录 事件监听驱动 与 异步事件源ApplicationContextAware接口 发布事件事件实体监听事件实现异步注入綫程池 事件驱动机制&#xff0c;与MQ消息队列比较 事件监听驱动 与 异步 事件监听驱动优点&#xff1a;解耦&#xff0c;将 事件和业务进行解耦&#xff0c;通过Asyc注解…...

C++ 优先级队列用法详解与模拟实现

文章目录 C 优先级队列用法与模拟实现介绍用法头文件1.创建优先级队列priority_queue 2. 插入元素push 3. 删除元素pop 访问顶部元素top 检查优先级队列的大小size 检查优先级队列是否为空empty 模拟实现 C 优先级队列用法与模拟实现 介绍 优先级队列&#xff08;Priority Qu…...

Linux进阶之旅:深入探索Linux的高级功能

文章目录 Linux进阶之旅:深入探索Linux的高级功能1. Shell脚本编程2. 进程管理3. 网络管理4. 文本处理5. 系统监控6. 总结 Linux进阶之旅:深入探索Linux的高级功能 在上一篇博客中,我们对Linux操作系统进行了入门级的介绍,包括Linux的特点、发行版、安装方法以及基本使用。接下…...

【Java】内存可见性问题是什么?

文章目录 内存模型内存可见性解决方案volatile 内存模型 什么是JAVA 内存模型&#xff1f; Java Memory Model (JAVA 内存模型&#xff09;是描述线程之间如何通过内存(memory)来进行交互。 具体说来&#xff0c; JVM中存在一个主存区&#xff08;Main Memory或Java Heap Mem…...

Guava里一些比较常用的工具

随着java版本的更新提供了越来越多的语法和工具来简化日常开发&#xff0c;但是我们一般用的比较早的版本所以体验不到。这时就用到了guava这个包。guava提供了很多方便的工具方法&#xff0c;solar框架就依赖了guava的16.0.1版本&#xff0c;这里稍微介绍下。 一、集合工具类…...

在windows系统中【.gz.tar】和【.whl】文件分别应该怎么下载到conda的某个虚拟环境中

在 Windows 系统中&#xff0c;你可以按照以下步骤将 .gz.tar 和 .whl 文件下载到 Conda 的某个虚拟环境中&#xff1a; 激活虚拟环境&#xff1a;打开 Anaconda Prompt 或者命令行窗口&#xff0c;使用以下命令激活你想要安装文件的虚拟环境&#xff1a; conda activate <虚…...

Rust - 数据类型

Rust 是静态编译语言&#xff0c;在编译时必须知道所有变量的类型。 基于使用的值&#xff0c;编译器通常能推断出它的具体类型&#xff0c;但如果可能的类型比较多&#xff0c;例如把String转换为整数的parse方法&#xff0c;就必须添加类型的标注&#xff0c;否则编译会报错…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

JDK 17 序列化是怎么回事

如何序列化&#xff1f;其实很简单&#xff0c;就是根据每个类型&#xff0c;用工厂类调用。逐个完成。 没什么漂亮的代码&#xff0c;只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...