新闻中心

C# 怎么实现一个观察者模式_C# 观察者模式实现方法详解

2025-11-03
浏览次数:
返回列表
C#中实现观察者模式的核心是定义主题与观察者,通过接口、事件或IObservable方式实现状态变更时的自动通知,适用于事件驱动场景。

c# 怎么实现一个观察者模式_c# 观察者模式实现方法详解

在 C# 中实现观察者模式,核心是定义一个被观察对象(主题)和多个观察者,当主题状态发生变化时,自动通知所有注册的观察者。这种设计模式非常适合处理事件驱动的场景,比如 UI 更新、消息广播等。

观察者模式的基本结构

观察者模式包含两个主要角色:

  • Subject(主题):维护观察者列表,提供注册、注销和通知方法。
  • Observer(观察者):实现一个更新接口,用于接收主题的通知。

在 C# 中,可以通过接口和委托两种方式来实现。下面分别介绍具体做法。

使用接口手动实现观察者模式

定义观察者和主题接口,让具体类实现它们。

示例代码:

// 观察者接口
public interface IObserver
{
    void Update(string message);
}
<p>// 主题接口
public interface ISubject
{
void Attach(IObserver observer);
void Detach(IObserver observer);
void Notify(string message);
}</p><p>// 具体主题
public class NewsAgency : ISubject
{
private List<IObserver> _observers = new List<IObserver>();</p><pre class='brush:php;toolbar:false;'>public void Attach(IObserver observer) => _observers.Add(observer);
public void Detach(IObserver observer) => _observers.Remove(observer);

public void Notify(string news)
{
    foreach (var observer in _observers)
    {
        observer.Update(news);
    }
}

// 模拟新闻发布
public void PublishNews(string news)
{
    Console.WriteLine($"新闻机构发布:{news}");
    Notify(news);
}

}

// 具体观察者 public class NewsChannel : IObserver { private string _name;

public NewsChannel(string name) => _name = name;

public void Update(string message)
{
    Console.WriteLine($"{_name} 收到新闻:{message}");
}

}

使用示例:

var agency = new NewsAgency();
var channelA = new NewsChannel("央视");
var channelB = new NewsChannel("凤凰");
<p>agency.Attach(channelA);
agency.Attach(channelB);</p><p>agency.PublishNews("今日天气晴朗");</p><p>// 输出:
// 新闻机构发布:今日天气晴朗
// 央视 收到新闻:今日天气晴朗
// 凤凰 收到新闻:今日天气晴朗</p>

利用 C# 委托和事件简化实现

C# 的事件机制天生适合观察者模式。通过 eventdelegate,可以更简洁地实现松耦合通信。

示例代码:

public class Stock
{
    // 定义委托
    public delegate void PriceChangedHandler(string symbol, double price);
<pre class='brush:php;toolbar:false;'>// 定义事件
public event PriceChangedHandler PriceChanged;

private string _symbol;
private double _price;

public Stock(string symbol, double price)
{
    _symbol = symbol;
    _price = price;
}

public double Price
{
    get => _price;
    set
    {
        _price = value;
        OnPriceChanged(); // 触发事件
    }
}

protected virtual void OnPriceChanged()
{
    PriceChanged?.Invoke(_symbol, _price);
}

}

观察者订阅事件:

Musho Musho

AI网页设计Figma插件

Musho 76 查看详情 Musho

var stock = new Stock("AAPL", 150.0);
<p>// 订阅事件
stock.PriceChanged += (symbol, price) =>
{
Console.WriteLine($"股票 {symbol} 价格变更为:{price}");
};</p><p>stock.Price = 155.0; // 输出:股票 AAPL 价格变更为:155</p>

这种方式更符合 C# 的编程习惯,代码更简洁,且线程安全由语言机制部分保障。

使用 IObservable 和 IObserver 接口(响应式扩展)

C# 还提供了内置的 IObservableIObserver 接口,属于 .NET 的响应式扩展(Reactive Extensions, Rx),适用于更复杂的异步数据流场景。

public class Sensor : IObservable<double>
{
    private List<IObserver<double>> _observers = new List<IObserver<double>>();
<pre class='brush:php;toolbar:false;'>public IDisposable Subscribe(IObserver<double> observer)
{
    if (!_observers.Contains(observer))
        _observers.Add(observer);

    return new Unsubscriber(_observers, observer);
}

public void Measure(double value)
{
    foreach (var observer in _observers)
        observer.OnNext(value);
}

private class Unsubscriber : IDisposable
{
    private List<IObserver<double>> _observers;
    private IObserver<double> _observer;

    public Unsubscriber(List<IObserver<double>> observers, IObserver<double> observer)
    {
        _observers = observers;
        _observer = observer;
    }

    public void Dispose()
    {
        _observers.Remove(_observer);
    }
}

}

使用方式:

var sensor = new Sensor();
<p>var observer = new MyObserver();
var subscription = sensor.Subscribe(observer);</p><p>sensor.Measure(23.5); // 触发通知</p><p>subscription.Dispose(); // 取消订阅</p>

其中 MyObserver 需要实现 IObserver 接口。

基本上就这些。C# 提供了多种实现观察者模式的方式:手动接口实现适合学习原理,事件机制最常用也最自然,而 IObservable 则适用于高级异步场景。选择哪种方式取决于项目复杂度和需求。

以上就是C# 怎么实现一个观察者模式_C# 观察者模式实现方法详解的详细内容,更多请关注其它相关文章!


# 多个  # 湖北营销推广哪家好  # 渤海新区seo推广  # 建设网站最终的目标  # 抖音seo系统方案  # 校园网站推广活动有哪些  # 网站优化建设怎么做的  # 页面seo推广工具  # 网站程序建设  # 从化市网站建设价格表  # 乐云seo新闻发稿平台  # 相关文章  # 两种  # react  # 央视  # 新特性  # 游戏开发  # 你在  # 有哪些  # 今日  # 适用于  # gate  # .net  # c#  # ai 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 自定义Bag-of-Words实现:处理带负号的词汇权重  c++如何使用chrono库处理时间_c++标准库时间与日期操作  拼多多购物车商品数量无法修改如何处理 拼多多购物车操作优化方法  uc浏览器网页版入口 uc浏览器网页版最新网址  双系统安装时,如何设置默认启动系统? msconfig命令了解一下!  J*aScript中高效清空DOM列表元素:解决for循环中断与任务管理问题  J*aScript教程:根据元素文本内容动态设置背景色  qq邮箱日历功能怎么用_创建日程与会议邀请的技巧  yandex入口引擎手机版 yandex安卓版下载入口  Django模型中自动计算可用余额的实现方法  python3时间如何用calendar输出?  探索高级语言到C/C++的转译路径:以Go为例及内存管理策略  JUnit5/Mockito:优雅测试内部依赖与异常处理的实践  神经网络二分类模型训练异常:高损失与完美验证准确率的排查与修正  不同用户不同价格! 索尼开启账户个性化定价测试  汽水音乐在线解析 汽水音乐在线解析入口  处理动态列数据:J*a ArrayList的正确初始化与字符累加教程  海棠电脑版入口_通过电脑访问海棠官网阅读  lar*el怎么安全地存储和获取配置文件中的敏感信息_lar*el敏感信息安全存储方法  俄罗斯Yandex免登录入口_Yandex搜索引擎官网一键直达  Excel中VLOOKUP的第四个参数是干什么用的_Excel VLOOKUP第四参数作用解析  c++ 获取系统当前时间 c++时间戳获取方法  优化MinIO list_objects_v2 操作的性能瓶颈与最佳实践  CSS布局中意外空白:解决padding-top导致的顶部间距问题  Lar*el Form Request中唯一性验证在更新操作中的正确实现  格力空气能E5故障代码是什么情况_格力空气能E5代码解析与应对措施  Go调试环境为何无法启动_Go调试器启动失败原因与解决策略  Django通过AJAX异步上传图片并保存至模型的完整指南  Linux如何构建多环境配置管理_Linux多环境配置方案  铁路12306官网网页端快速入口 铁路12306官方首页登录教程  UC浏览器官网入口2025最新 UC浏览器网页版正式地址  2026年CSGO开箱网站推荐 CSGO开箱平台精选  印象笔记如何设离线包出差查阅_印象笔记设离线包出差查阅【离线阅读】  Django AJAX 文件上传教程:解决图片无法保存到模型的常见问题  Surface怎么安装系统 微软Surface Pro U盘重装win11教程  蛙漫官方正版入口 蛙漫网页在线全集免费观看  composer的"require-dev"部分是用来做什么的?  汽水音乐车机版横屏版7.1 汽水音乐车机版横屏版下载入口  Python中如何避免重复条件判断:利用数据结构实现动态逻辑  C++如何操作注册表_Windows平台下C++读写注册表的API函数详解  魅族17怎样用浏览器译外语网页_iPhone魅族17浏览器译外语网页【即时翻译】  Word2013如何插入视频和音频媒体_Word2013媒体插入的多媒体支持  FullCalendar 自定义按钮样式定制指南  Windows7怎么硬盘安装 Windows7提取ISO镜像到非系统盘并运行setup.exe实现硬盘直装【教程】  J*a 递归快速排序中静态变量的状态管理与陷阱  蛙漫画网页版全站入口 蛙漫热门作品免费浏览  整合Supabase认证与Django模型:跨模式迁移的解决方案  HTML元素状态管理:根据DIV内容动态启用/禁用按钮  如何使用J*aScript精确选择并批量修改特定父元素下子链接的样式  2306选座时如何选靠窗位置_12306选座靠窗座位查看方法解析 

搜索