C#实现观察者模式(Observer Pattern)的两种方式
作者:Darren?Ji 发布时间:2023-06-20 21:05:18
标签:C#,观察者,模式,Observer,Pattern
在观察者模式中有2个要素:一个是被观察对象,另一个是观察者。但被观察对象的状态发生改变会通知观察者。
举例:把订阅报纸的人看作是观察者,把报纸看作被观察对象。每当有新的新闻就要通知订阅报纸的人。本篇分别用实现接口和使用委托事件的方式来实现。
通过实现接口实现
观察者接口,把接收到的新闻显示出来。
public interface IObserver
{
void Update(string news);
}
被观察对象接口,提供3个方法:注册观察者,取消观察者,通知观察者。
public interface ISubject
{
void RegisteerObserver(IObserver o);
void RemoveObserver(IObserver o);
void NotifyObservers();
}
被观察对象实现类,维护着一个观察者接口的集合,对观察者的注册和取消实际上是往这个集合添加或移除数据。
public class NewsPublisher : ISubject
{
private List<IObserver> observers = new List<IObserver>();
private List<string> newsList = new List<string>();
public void RegisteerObserver(IObserver o)
{
observers.Add(o);
}
public void RemoveObserver(IObserver o)
{
observers.Remove(o);
}
public void NotifyObservers()
{
foreach (IObserver o in observers)
{
o.Update(newsList[newsList.Count - 1]);
}
}
public void PublishNews(string news)
{
newsList.Add(news);
NotifyObservers();
}
}
另外,被观察对象实现类还维护着一个string类型的新闻集合,每当发布新闻,就往这个集合里添加数据,并通知所有的注册观察者。
观察者的实现类。
public class NewsSubscriber : IObserver
{
public void Update(string news)
{
Console.WriteLine("收到通知了");
Console.WriteLine(news);
}
}
客户端,被观察对象注册观察者并触发动作。
class Program
{
static void Main(string[] args)
{
NewsPublisher publisher = new NewsPublisher();
NewsSubscriber subscriber = new NewsSubscriber();
publisher.RegisteerObserver(subscriber);
publisher.PublishNews("看报,看报,快来看报~");
Console.ReadKey();
}
}
使用委托事件实现
看到以上的做法,委托和事件这对好朋友就笑了。注册、取消观察者还得用2个方法,那让我们情何以堪?我们这样做:
观察者类只负责对收到的新闻显示。
public class NewsSubscriber
{
public void Update(string news)
{
Console.WriteLine("收到新闻了~");
Console.WriteLine(news);
}
}
被观察对象类用到了委托和事件。
public class NewsPublisher
{
private readonly List<string> newsList = new List<string>();
public delegate void NotifyOvserversHandler(string news);
public event NotifyOvserversHandler newsPublished;
public void PublishNews(string news)
{
newsList.Add(news);
newsPublished(newsList[newsList.Count - 1]);
}
}
以上,委托声明了方法的定义,接收一个string类型参数,返回void。事件负责对符合委托定义的、观察者方法的注册和取消。
在客户端使用事件对方法进行注册。
class Program
{
static void Main(string[] args)
{
NewsPublisher publisher = new NewsPublisher();
NewsSubscriber subscriber = new NewsSubscriber();
publisher.newsPublished += subscriber.Update;
publisher.PublishNews("现在是看报时间~");
Console.ReadKey();
}
}
与通过接口实现不同,使用事件注册的是观察者的方法,而不是观察者本身。
总结:无论通过接口实现,还是使用委托和事件,观察者模式的要素是不变的:被观察对象,观察者,被观察者提供注册、取消观察者或观察者方法,通过被观察对象的某个方法触发、通知观察者。
来源:https://www.cnblogs.com/darrenji/p/3966626.html
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- properties和yml的区别这几天刚好看到Spring Boot当中有两种配置文件的方式,但是这两种配置方式有什么区别呢?proper
- 一、进程内部的线程同步1、使用lock,用法如下:private static readonly object SeqLock = new
- 本文实例讲述了Winform中GridView分组排序功能实现方法。分享给大家供大家参考。具体实现方法如下:一、问题:由于客户最近要扩充公司
- 一、需求分析:1、输入一个数组-----------------------------------------》程序要接收一组输入的数组,
- 本文实例为大家分享了java计算工作时间的具体代码,不包括节假日、双休日,供大家参考,具体内容如下package common.util;
- 目录1 起因2 解决方案2.1 在pom中引入2.2 Spring Boot 打包处理2.3 拓展: Spring Boot 打包加入其它资
- C#的FileInfo类提供了与File类相同的功能,不同的是FileInfo提供的都是成员方法,使用示例如下所示:1、读文件://创建只读
- 1.EazyEmail邮件发送类库Net 类库自带了邮件发送功能。笔者对该类库,从使用的角度进行了二次封装,nuget上可搜索EazyEma
- 本文实例讲述了Android实现图片轮播效果代码,分享给大家供大家参考。具体如下:运行效果截图如下:具体代码如下:首先看下一下布局文件:&l
- 前言去年7月时,在Github发布了一个开源的Banner库,虽然Star不多,但还是有少部分人使用。Banner效果:Github链接地址
- 本文实例讲述了C#实现左截取和右截取字符串的方法,分享给大家供大家参考。具体方法分析如下:问题如下:使用C#语法编写程序时,我们需要截取一个
- springboot静态资源加载顺序优先级看springboot源码里面springboot静态资源加载规则我们经常会使用springboo
- 本文实例讲述了Android测量每秒帧数Frames Per Second (FPS)的方法。分享给大家供大家参考。具体如下:MainThr
- 本文实例讲述了Android开发使用自定义View将圆角矩形绘制在Canvas上的方法。分享给大家供大家参考,具体如下:前几天,公司一个项目
- 1.Nuget搜索Tesseract2.项目安装Tesseract3.引用命名空间using Tesseract;4.上Github下载别人
- 本文实例为大家分享了C#实现图表中鼠标移动并显示数据的具体代码,供大家参考,具体内容如下效果图:1.首先在页面上添加一个label控件并 默
- 本文实例讲述了Android基于AlarmManager实现用户在线心跳功能。分享给大家供大家参考,具体如下:在做即时通信或者其他检测是否在
- 第一次进入应用的时候,都会有一个引导页面,引导页面的实现起来也很简单,实现的方式也有很多,下面是自己写的一个引导页面的效果,大致的实现思路为
- APP中可能会遇到一种需求,就是将当前所在位置的坐标传到服务器上,今天我提供三种途径去获取经纬度坐标信息,第一种是通过Android API
- @RequestParam设置默认可以传空值设置如下@RequestParam(value="CbqkJson[]",r