C#观察者模式应用

目录

一、什么是观察者模式

二、C#中观察者模式的实现

三、两种实现的用法

1、事件与委托

2、IObserver和IObservable

四、参考文献


一、什么是观察者模式

观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式(Publish-Subscribe)、模型-视图(Model-View)模式、源监听器(Source-Listener)或者从属者模式,它是对象行为型模式。

  • 模型(Model) -发布者是数据源,模型层, 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。
  • 视图(View) -监听者是视图层, 界面设计人员进行图形界面设计。

观察者模式是一种对象行为型模式,其主要优点如下。

  1. 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
  2. 目标与观察者之间建立了一套触发机制。

它的主要缺点如下。

  1. 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
  2. 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。

二、C#中观察者模式的实现

C#语言,其事件和委托本身就是观察者模式的基本实现。除此之外,属性修改通知以及属性依赖等也是观察者模式的用途之一,在WinForm或者WPF中,通常将集合类控件,绑定到集合上,当集合数据发生变化时,绑定的控件能够得到通知,并且能够自动刷新界面。

    在C#中使用观察者模式,除了常用的event事件之外,还可以通过IObservable<T>和IObserver<T>两个接口来实现事件流模式,看起来有些复杂,但是这种方式有很多优点,并且很容易能跟Reactive Extensions框架配合。最后讲述了Observerable集合BindingList<T>和ObservableCollection<T>,他们不是线程安全的,使用的时候需要注意多线程读写的问题,这两个集合通常跟配套的支持集合的控件来绑定使用,这样能做到当集合数据发生变化时,对应的界面能够自动刷新。

在软件世界也是这样,例如,Excel 中的数据与折线图、饼状图、柱状图之间的关系;MVC 模式中的模型与视图的关系;事件模型中的事件源与事件处理者。所有这些,如果用观察者模式来实现就非常方便。

C#的设计者通过关键字event来简化对观察者模式的使用。它的基本用法是,首先使用event关键字定义事件,然后注册事件回调方法EventHandler,回调方法通常包含两个参数,一个object类型的sender和一个继承自EventArgs的参数,该参数携带一些触发事件的必要信息。

三、两种实现的用法

1、事件与委托

    event事件其实是对委托的包装。对event的包装成为EventHandler,有泛型和非泛型版本,泛型主要是继承自EventArgs的类型。具体使用可以了解如何使用event定义事件。并且由此了解Action Func的用法,加深对委托的理解。

2、IObserver<T>和IObservable<T>

  如果将一个List<T>绑定到WinForm或者WPF中的ListBox,当List发送改变的时候,UI不会更新,这是因为List<T>并不支持Observer模式。当然如果单个对象发生改变,但整个List并没有事件能够向外通知其内容发送了改变。诚然我们可以对List进行包装,在Add或者Remove方法里添加事件通知,可以但没必要,在WinForm和WPF中都有Observable集合,他们分别是BindingList<T>和ObservableCollection<T>。

    这两个集合类型表现起来就跟Collection<T>一样,但是他提供了额外的通知。比如,对于UI组件,当绑定的集合发送改变时,UI会自动进行更新。ObservableCollection<T>实现了INotifyCollectionChanged接口,所以他有CollectionChanged事件。这个时间会告知集合发生了什么改变,并且会提供旧的和新的元素,以及旧的和新的元素在集合中的位置,换句话说,根据事件我们能够正确的重新绘制ListBox或者其他集合组件。

    需要注意的是BindingList<T>和ObservableCollection<T>都不是线程安全的集合,因此在多线程读写集合的时候,需要特别注意。一种方式是继承自Observable集合,然后对一些写入操作加锁。另外一种方法是继承自ConcurrentBag<T>,然后实现INotifyCollectionChanged接口。相对而言,第一种方式简单一些。

IObservable<T>和IObserver<T> 类型的代码

Weather weather = new Weather() {  Teapreture=new WeatherData { temperature="25度"} };
Person wanglin = new Person() { Name="王玲"};
Person mulan = new Person() { Name = "木兰" };
weather.Subscribe(wanglin);///Subscribe 等同于 事件的"+"
weather.Subscribe(mulan);//
weather.NotifyTeapreture();//公告温度
Console.Read();
/// <summary>
/// 订阅者
/// </summary>
public class Person : IObserver<WeatherData>
{//关注温度public string Name { get; set; }public void OnCompleted(){Console.WriteLine(" ");}public void OnError(Exception error){throw new NotImplementedException();}public void OnNext(WeatherData value){Console.WriteLine($"我{Name}知道今天的天气了,是{value.temperature}");}
}
/// <summary>
/// 数据
/// </summary>
public class WeatherData
{/// <summary>/// 气温/// </summary>public string temperature { get; set; }/// <summary>/// 湿度/// </summary>public string humility { get; set; }/// <summary>/// 气压/// </summary>public string pressure { get; set; }
}
/// <summary>
/// 发布者
/// </summary>
public class Weather : IObservable<WeatherData>
{//提供温度 数据public WeatherData Teapreture { get; set; }private List<IObserver<WeatherData>> subsribers = new List<IObserver<WeatherData>>();public IDisposable Subscribe(IObserver<WeatherData> observer){if (!subsribers.Contains(observer)){subsribers.Add(observer);}return new UnSubsribe(this, observer);}class UnSubsribe : IDisposable{private Weather weather;private IObserver<WeatherData> observer;public UnSubsribe(Weather weather, IObserver<WeatherData> observer){this.weather = weather;this.observer = observer;}public void Dispose(){weather.subsribers.Remove(observer);}}public void NotifyTeapreture(){foreach (var item in subsribers){item.OnNext(Teapreture);}}public void OnComplete(){foreach (var item in subsribers){item.OnCompleted();}}}

四、参考文献

【C# 设计模式】观察者模式 - 小林野夫 - 博客园 (cnblogs.com)

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

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

相关文章

探索AIGC与3D技术的融合:从图像到可探索的3D动态场景

随着人工智能和计算机图形技术的飞速发展,AIGC(人工智能生成内容)与3D技术的结合正在为我们打开一扇全新的创意之门。最近,我深入研究了几个令人兴奋的AIGC+3D方案,它们不仅展示了从单张图片或文本提示生成3D点云的强大能力,还进一步实现了AI虚拟试穿和生成高保真3D数字人…

java对象的创建和使用

java中&#xff0c;定义一个类之后&#xff0c;需要创建该类的对象才能使用这个类 创建对象的具体格式是 类名 对象名null 对象名new 类名 这两步可以合并为一步 类名 对象名 new 类名 class Student{String name;void read() {System.out.println("大家好&#xff…

【PX4-AutoPilot教程-TIPS】离线安装Flight Review PX4日志分析工具

离线安装Flight Review PX4日志分析工具 安装方法 安装方法 使用Flight Review在线分析日志&#xff0c;有时会因为网络原因无法使用。 使用离线安装的方式使用Flight Review&#xff0c;可以在无需网络的情况下使用Flight Review网页。 安装环境依赖。 sudo apt-get insta…

如何做到修改 url 参数页面不刷新

HTML5 引入了 history.pushState() 和 history.replaceState() 方法&#xff0c;它们分别可以添加和修改历史记录条目。 let stateObj {foo: "bar" };history.pushState(stateObj, "page 2", "bar.html"); 假设当前页面为 foo.html &#xff…

安徽京准-NTP网络授时服务器助力助力甘南州公共资源交易

安徽京准-NTP网络授时服务器助力助力甘南州公共资源交易 安徽京准-NTP网络授时服务器助力助力甘南州公共资源交易 2024年5月中旬&#xff0c;我安徽京准科技生产研发的NTP时钟服务器成功投运甘南州公共资源交易中心&#xff0c;为该中心的计算机网络系统及其他各业务子系统提供…

串口屏介绍

一、串口屏简介 串口屏&#xff08;Serial LCD/Serial TFT Display&#xff09;是一种集成了串行通讯功能的显示屏&#xff0c;广泛应用于各种嵌入式系统、工业控制、人机界面&#xff08;HMI&#xff09;等领域。该显示屏通过串口&#xff08;如UART、RS232、RS485等&#xf…

研究认为要解决社会偏见 就必须关注语言的文化传播

发表在《社会心理学与人格科学》&#xff08;Social Psychological and Personality Science&#xff09;杂志上的一项新研究中&#xff0c;研究人员分享了人们的态度与语言和文化深深交织在一起的证据。 研究人员发现&#xff0c;全球民众的态度与语言相关&#xff0c;揭示了…

【面试干货】Java集合类详解:List、Set、Queue、Map、Stack的特点与用法

【面试干货】Java集合类详解&#xff1a;List、Set、Queue、Map、Stack的特点与用法 1、Map1.1 特点1.2 用法1.3 常见的实现类 2、Set2.1 特点2.2 用法2.3 常见的实现类 3、List3.1 特点3.2 用法3.3 常见的实现类 4、Queue4.1 特点4.2 用法4.3 常见的实现类 5、Stack5.1 特点5.…

网络安全的未来趋势:预测与准备

# 网络安全的未来趋势&#xff1a;预测与准备 随着技术的飞速发展&#xff0c;网络安全领域正面临着前所未有的挑战和变革。预测未来网络安全的趋势并做好相应的准备&#xff0c;对于保护数字资产和个人隐私至关重要。本文将探讨网络安全的未来趋势以及组织和个人应如何准备应…

FastWeb - Lua开源跨平台网站开发服务

在网站开发领域&#xff0c;大家都熟知PHPStudy和宝塔这两款广受欢迎的工具&#xff0c;但今天我要介绍的是一款功能强大、支持跨平台的开源Lua网站开发服务——Fast Web&#xff0c;以及与之配套的网站管理器。 Fast Web简介 Fast Web是一款基于Lua编写的网站开发框架&#…

注解 - @ResponseStatus

注解简介 在今天的每日一注解中&#xff0c;我们将探讨ResponseStatus注解。ResponseStatus是Spring框架中的一个注解&#xff0c;用于为控制器方法指定HTTP响应状态码和理由短语。 注解定义 ResponseStatus注解用于标记控制器方法或异常类&#xff0c;以指示HTTP响应的状态码…

基于Flask+Mysql+EasyUI的简单用户管理系统

1、系统实现功能 添加用户查看用户修改用户删除用户 完整代码下载地址在最后&#xff0c;若显示链接不存在&#xff0c;可能是资源还没有审核&#xff0c;可私聊我发完整代码。 2、功能实现 2.1 添加用户 构建添加用户的Flask接口add_user() app.route("/add/user&quo…

依赖自动装配

黑马程序员SSM框架 文章目录 1、依赖自动装配2、依赖自动装配的特征 1、依赖自动装配 IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配自动装配方式 按类型&#xff08;常用&#xff09;按名称按构造方法不启用自动装配 配置中使用bean标签auto…

React小记(三)_函数组件的使用

1、创建项目 npx create-react-app myReact2、启动项目 cd myReactnpm start3、jsx语法 1、只能有一个根标签/<></>2、所有标签必须闭合3、jsx语法要写在小括号()里面 !!!4、插值 { } 1、插值可以使用的位置标签内容标签属性2、{ }里面为js语句【代码】 function A…

使用 MPLS 解决 BGP 的路由黑洞

MPLS 协议并不会为通过 BGP 协议学习的路由条目分配标签号&#xff1b; 而是在访问这些 BGP 路由目标网段时&#xff0c;在流量中压入到达这些网段的 BGP 下一跳设备地址的标签号&#xff1b; 例&#xff1a;R2从BGP邻居5.5.5.5学习到6.6.6.0 网段的路由&#xff1b;R2在访问…

网络编程入门介绍:TCP 和 UDP

目录 简介TCP&#xff1a;传输控制协议 TCP 的特点TCP 如何工作TCP 示例TCP 实践样例 UDP&#xff1a;用户数据报协议 UDP 的特点UDP 如何工作UDP 示例UDP 实践样例 TCP 与 UDP 的比较总结 简介 在计算机网络中&#xff0c;TCP&#xff08;传输控制协议&#xff09;和 UDP&a…

2024年6月15日 十二生肖 今日运势

小运播报&#xff1a;2024年6月15日&#xff0c;星期六&#xff0c;农历五月初十 &#xff08;甲辰年庚午月庚戌日&#xff09;&#xff0c;法定节假日。 红榜生肖&#xff1a;兔、马、虎 需要注意&#xff1a;牛、鸡、龙 喜神方位&#xff1a;西北方 财神方位&#xff1a;…

【数学】如何求解矩阵的特征值和特征向量

文章目录 如何求解矩阵的特征向量背景公式示例题目详细讲解Python代码求解实际生活中的例子本质解释 如何求解矩阵的特征向量 背景 特征向量和特征值是线性代数中的重要概念&#xff0c;广泛应用于物理学、计算机科学&#xff08;如机器学习、图像处理&#xff09;和统计学等…

摄像头校准之白平衡畸变坏点

摄像头校准之白平衡&畸变&坏点 1. 源由2. 校准内容3. 畸变校准一、畸变模型二、校准步骤1. 准备工作2. 特征点检测3. 计算内参数和畸变系数4. 畸变校正 三、验证和优化1. 视觉验证2. 误差评估3. 参数优化 4. 白平衡校准一、白平衡基础二、自动白平衡&#xff08;AWB&am…

AI 客服定制:LangChain集成订单能力

为了提高AI客服的问题解决能力&#xff0c;我们引入了LangChain自定义能力&#xff0c;并集成了订单能力。这使得AI客服可以根据用户提出的问题&#xff0c;自动调用订单接口&#xff0c;获取订单信息&#xff0c;并结合文本知识库内容进行回答。这种能力的应用&#xff0c;使得…