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
0
投稿
猜你喜欢
- idea激活码破解教程亲测试以下版本成功激活附激活教程。idea下载链接(对应版本号下载):https://www.jetbrains.co
- 讲这个例子前,咱们先来看一个简单的程序:字符串数组实现数字转字母:#include <stdio.h>#include <
- IntelliJ IDEA 2021最新激活码超详细教程,成功激活到2099年。每天专业人士测试,保证可以使用才分享给大家的,放心大胆使用哈
- 首先打开 Visual Studio Installer 可以看到vs2022 只支持安装4.6及以上的版本,如图所示。那么该如何安装4.6
- 背景大家在使用Selenium + Chromedriver爬取网站信息的时候,以为这样就能做到不被网站的反爬虫机制发现。但是实际上很多参数
- 目录样例代码在讲 Flutter 的盒子模型前,先看看HTML 中的盒子模型。如下图所示,一个页面元素包括了与父级容器的外边距(margin
- 简介对于一个APP来说,肯定会有一个AppBar,这个AppBar一般包含了APP的导航信息等。虽然我们可以用一个固定的组件来做为AppBa
- 最近“全网域(Web Scale)”一词被炒得火热,人们也正在通过扩展他们的应用程序架构来使他们的系统变得更加“全网域”。但是究竟什么是全网
- 无论哪种界面框架输入文本框都是非常重要的控件, 但是发现flutter中的输入框TextField介绍的虽然多,但是各个属性怎么组合满足需要
- 需求:有些时候,我们需要连接多个数据库,但是,在方法调用前并不知道到底是调用哪个。即同时保持多个数据库的连接,在方法中根据传入的参数来确定。
- yaml语法注解配置文件两种形式application.properties和.yaml第一种语法 key=value第二种key:空格va
- [LeetCode] 9. Palindrome Number 验证回文数字Determine whether an integer is
- 前言当系统的并发比较高的时候,日志的处理输出也是一种性能的开销负担,所以,选择一个中间件来处理消费日志必不可少!下面是spring boot
- webp格式图片webp格式图片是google推出的,相比jpg png有着巨大的优势,同样质量的图片webp格式的图片占用空间更小,在像电
- 前言在使用Java开发接口请求中,我们需要对请求进行进行统一返回值,这时候我们自己封装一个统一的Result返回类,下面就介绍下我用的这种的
- 在使用springMVC框架构建web应用,客户端常会请求字符串、整型、json等格式的数据,通常使用@ResponseBody注解使 co
- 前言开发中,免不了会用到多边形、多角星等图案,比较常用的多边形比如雷达图、多角星比如评价星级的五角星等,本篇文章就使用Flutter绘制封装
- 目录效果展示剪裁 WidgetClipRRect(圆角矩形剪裁)其他属性其他形状剪裁ClipOval(椭圆剪裁)其他属性ClipRect(矩
- 本文实例讲述了java实现的简单猜数字游戏代码。分享给大家供大家参考。具体代码如下:import java.util.InputMismat
- 可以静态绑定数据源,这样就自动为DataGridView控件添加 相应的行。假如需要动态为DataGridView控件添加新行,方法有很多种