.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");。这样就会触发通知所有注册的观察者。}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/818087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分类算法(数据挖掘)

目录 1. 逻辑回归&#xff08;Logistic Regression&#xff09; 2. 支持向量机&#xff08;Support Vector Machine, SVM&#xff09; 3. 决策树&#xff08;Decision Tree&#xff09; 4. 随机森林&#xff08;Random Forest&#xff09; 5. K近邻&#xff08;K-Nearest …

Vue3(三):生命周期、路由、自定义hooks

这里终于明白了为什么一直有这个语法报错&#xff0c;就是在提示你哪里错的地方上方注释一行/*eslint-disable*/&#xff0c;之前一直警告这个错误感谢老师&#xff01; 一、vue2和vue3生命周期 还有一个问题就是父组件和子组件哪个先挂载完毕呢&#xff1f;答案是子组件先挂…

Qt---控件的基本属性

文章目录 enabled(控件可用状态)geometry(位置和尺寸)简单恶搞程序 windowIcon(顶层 widget 窗口图标)使用 qrc 机制 windowOpacity(窗口的不透明值)cursor(当鼠标悬停空间上的形状)自定义鼠标图标 toolTip(鼠标悬停时的提示)focusPolicy(控件获取焦点的策略)styleSheet(通过CS…

【Python实践应用】使用Python加载栅格数据

下面的代码实现的是加载伊宁市NDVI数据&#xff0c;首先进行相关的python包的导入&#xff0c;然后定义和读取我们需要加载的数据&#xff0c;这里我们使用的NDVI数据是将伊宁23年的NDVI数据合并成为了一张栅格图像&#xff0c;每个波段表示一年的 NDVI&#xff0c;我们这里显示…

web前端之element级联选择器的那些事、获取label的值、getCheckedNodes、cascader、ref

MENU 动态加载时获取value和label的值 动态加载时获取value和label的值 前言 1、使用ref的getCheckedNodes方法获取label的值&#xff0c;change事件只传递value值&#xff1b; 2、回显自动处理&#xff0c;无需手动干预&#xff0c;设置好接口即可。 html <el-cascader r…

MySQL学习笔记3——条件查询和聚合函数

条件查询和聚合函数 一、条件查询语句二、聚合函数1、SUM&#xff08;&#xff09;2、AVG()、MAX()、MIN()3、COUNT&#xff08;&#xff09; 一、条件查询语句 WHERE 和 HAVING 的区别&#xff1a; WHERE是直接对表中的字段进行限定&#xff0c;来筛选结果&#xff1b;HAVIN…

最新版IntelliJ IDEA 2024.1安装和配置教程 详细图文解说版安装教程

IntelliJ IDEA 2024.1 最新版如何快速入门体验?IntelliJ IDEA 2024.1 安装和配置教程 图文解说版 文章目录 IntelliJ IDEA 2024.1 最新版如何快速入门体验?IntelliJ IDEA 2024.1 安装和配置教程 图文解说版前言 第一步&#xff1a; IntelliJ IDEA 2024.1安装教程第 0 步&…

Java快速入门系列-7(测试与调试)

第七章:测试与调试 第7章:测试与调试7.1 单元测试(JUnit)7.1.1 为什么要进行单元测试7.1.2 JUnit基础7.1.3 断言7.1.4 测试套件7.2 集成测试与系统测试7.2.1 集成测试7.2.2 系统测试7.3 调试技巧与工具7.3.1 断点7.3.2 单步执行7.3.3 变量检查7.3.4 条件断点7.3.5 日志记录…

Playwright已经是目前最好的测试自动化工具了吗?

作者观点&#xff1a;很长时间以来&#xff0c;Selenium是QA工程师寻求测试自动化解决方案的首选测试框架。它能够测试任何浏览器&#xff08;这在IE浏览器的统治时期尤其重要&#xff09;和任何平台。然而&#xff0c;现在看来&#xff0c;那个时代已经过去了。 今天&#xf…

【嵌入式】SD NAND:小身躯蕴含大能量的新型嵌入式存储解决方案

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

当Mac的hosts文件被永久锁定后的解锁方法

M3 2024新机器因为要下载一些插件包&#xff0c;需要修改hosts文件 按常规操作去修改hosts的访问权限时&#xff0c;却发现怎样也改变不了&#xff0c;在命令行方式下用sudo vim访问&#xff0c;保存时也提示异常 在网上找了一些资料&#xff0c;终于知道Mac的文件有永久锁定…

如何在Linux通过docker搭建Plik文件系统并实现无公网IP管理内网文件

文章目录 1. Docker部署Plik2. 本地访问Plik3. Linux安装Cpolar4. 配置Plik公网地址5. 远程访问Plik6. 固定Plik公网地址7. 固定地址访问Plik 本文介绍如何使用Linux docker方式快速安装Plik并且结合Cpolar内网穿透工具实现远程访问&#xff0c;实现随时随地在任意设备上传或者…

JNI用法

提示&#xff1a;文章 文章目录 前言一、背景二、 2.1 2.2 总结 前言 前期疑问&#xff1a; 本文目标&#xff1a; 一 背景 之前搞过jni&#xff0c;之前是强哥指导搞的&#xff0c;现在感觉又忘了。 今天照着帖子再搞一次。参考帖子&#xff1a;https://blog.csdn.net/y…

JWT介绍

JWT JSON Web Token (JWT) 是一种开放标准 (RFC 7519)&#xff0c;提供一种简洁且自包含的方式&#xff0c;以JSON形式在通信双方间传递信息。这些信息可通过数字签名进行验证&#xff0c;确保其可信度。JWT 可以使用密钥&#xff08;HMAC&#xff09;或 RSA 或 ECDSA 的公钥/…

React-hooks:useReducer

useReducer 文档地址 useReducer 是一个 React Hook&#xff0c;它允许你向组件里面添加一个 reducer。 对于拥有许多状态更新逻辑的组件来说&#xff0c;过于分散的事件处理程序可能会令人不知所措。对于这种情况&#xff0c;你可以将组件的所有状态更新逻辑整合到一个外部函…

一文读懂Uniapp的setStorage、setStorageSync、getStorage以及getStorageSync(附Demo)

目录 前言1. uni.setStorage 和 uni.getStorage2. uni.setStorageSync 和 uni.getStorageSync3. 比较 前言 将登陆信息存储在本地&#xff0c;后续将相关信息应用在其他的业务 这类功能需要使用到这几个函数 以及 uni.setStorage 和 uni.getStorage 以及 uni.setStorageSync …

前端 接口返回来的照片太大 加载慢如何解决

现象 解决 1. 添加图片懒加载 背景图懒加载 对背景图懒加载做的解释 和图片懒加载不同&#xff0c;背景图懒加载需要使用 v-lazy:background-image&#xff0c;值设置为背景图片的地址&#xff0c;需要注意的是必须声明容器高度。 <div v-for"img in imageList&quo…

交叉熵损失函数介绍

交叉熵是信息论中的一个重要概念&#xff0c;它的大小表示两个概率分布之间的差异&#xff0c;可以通过最小化交叉熵来得到目标概率分布的近似分布。 为了理解交叉熵&#xff0c;首先要了解下面这几个概念。 自信息 信息论的基本想法是&#xff0c;一个不太可能的事件发生了…

Centos7源码安装Nginx

1. 安装相关依赖 这一步是针对服务器可能是最小化安装的&#xff0c;有些依赖是没有的情况。 服务器可以联网 则执行1.1否则执行1.2 1.1. 可以联网安装依赖 服务器可以联网 则执行这一步安装相关依赖 # 安装nginx需要先将官网下载的源码进行编译&#xff0c;编译依赖gcc环…