在 C# 中,如何实现观察者模式?

观察者模式是一种设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当该主题对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。这个模式常用于事件处理系统、通知系统等场景。

  • 主题(Subject):主题对象持有一个观察者列表,当自身状态发生变化时,通知所有观察者。通常包含方法来添加和移除观察者。
  • 观察者(Observer):一个接口或抽象类,当它所观察的主题状态发生变化时接受通知。每个观察者都实现一个更新方法,该方法会在主题状态改变时被调用。
  • 具体主题(Concrete Subject):具体实现的主题,并在状态发生变化时,通知观察者。
  • 具体观察者(Concrete Observer):具体实现的观察者,在接收到主题通知时执行相应的动作。

简单解释

想象一下,你是一本报纸的编辑(主题),有许多订阅者(观察者)想要在你出版新文章时被通知。当你完成一篇新文章时,你就会通知所有的订阅者。这就是观察者模式的基本思想。

  1. 定义观察者接口
csharp 复制代码
// 定义一个观察者接口,所有的订阅者都需要实现这个接口
public interface ISubscriber
{
    // 更新方法,当主题有新消息时调用
    void Update(string article);
}
  1. 实现具体的观察者
csharp 复制代码
// 实现具体的观察者类
public class Subscriber : ISubscriber
{
    private string name;

    // 构造函数,用于初始化订阅者的姓名
    public Subscriber(string name)
    {
        this.name = name;
    }

    // 当收到新文章的通知时,输出相关信息
    public void Update(string article)
    {
        Console.WriteLine($"{name} 收到了新文章: {article}");
    }
}
  1. 定义主题接口
csharp 复制代码
// 定义主题接口,收集和管理所有订阅者
public interface INewsPaper
{
    // 添加订阅者
    void Subscribe(ISubscriber subscriber);

    // 移除订阅者
    void Unsubscribe(ISubscriber subscriber);

    // 发布新文章,通知所有订阅者
    void PublishArticle(string article);
}
  1. 实现具体的主题
csharp 复制代码
using System.Collections.Generic;

// 实现具体的主题类
public class NewsPaper : INewsPaper
{
    // 用于保存所有订阅者的列表
    private List<ISubscriber> subscribers = new List<ISubscriber>();

    // 添加新订阅者到列表
    public void Subscribe(ISubscriber subscriber)
    {
        subscribers.Add(subscriber);
    }
    // 从列表中移除订阅者
    public void Unsubscribe(ISubscriber subscriber)
    {
        subscribers.Remove(subscriber);
    }
    // 当有新文章时,通知所有订阅者
    public void PublishArticle(string article)
    {
        Console.WriteLine($"出版新文章: {article}");
        foreach (var subscriber in subscribers)
        {
            // 调用每个订阅者的更新方法
            subscriber.Update(article);
        }
    }
}
  1. 使用示例
csharp 复制代码
class Program
{
    static void Main(string[] args)
    {
        // 创建一个报纸对象
        NewsPaper newsPaper = new NewsPaper();

        // 创建订阅者对象
        ISubscriber alice = new Subscriber("Alice");
        ISubscriber bob = new Subscriber("Bob");

        // 订阅者 Alice 和 Bob 订阅了报纸
        newsPaper.Subscribe(alice);
        newsPaper.Subscribe(bob);

        // 发布新文章,订阅者会收到通知
        newsPaper.PublishArticle("观察者模式在C#中的使用");

        // Bob 决定退订不再接收新文章
        newsPaper.Unsubscribe(bob);

        // 发布另一篇文章,只有 Alice 会收到通知
        newsPaper.PublishArticle("C#编程实用技巧");
    }
}

运行结果

解释

  • ISubscriber 和 INewsPaper 是接口,定义了订阅者和报纸需要的功能。
  • Subscriber 是具体的观察者,收到新文章的通知后,会输出一条消息。
  • NewsPaper 是具体的主题,保存了一组订阅者,并在每次发布新文章时通知他们。
  • 在 Main 方法中,我们创建了一份报纸和两个订阅者,这些订阅者在文章发布时会收到通知。
相关推荐
一心赚狗粮的宇叔11 小时前
oracle使用CTE递归分解字符串
mysql·oracle·c#·database
小码编匠14 小时前
WPF 自定义按钮样式(添加依赖属性、圆角)
后端·c#·.net
dangoxiba15 小时前
[Unity Demo]从零开始制作空洞骑士Hollow Knight第十八集补充:制作空洞骑士独有的EventSystem和InputModule
游戏·unity·c#·游戏引擎·playmaker
无敌最俊朗@15 小时前
unity3d————屏幕坐标,GUI坐标,世界坐标的基础注意点
开发语言·学习·unity·c#·游戏引擎
界面开发小八哥15 小时前
界面控件DevExpress WPF中文教程:Data Grid——卡片视图概述
.net·wpf·界面控件·devexpress·ui开发
.net开发15 小时前
WPF使用Prism框架首页界面
前端·c#·.net·wpf
Crazy Struggle18 小时前
.NET 8 高性能跨平台图像处理库 ImageSharp
.net·imagesharp·图像库·图像处理库
浪里个浪的102418 小时前
【C#】选课程序增加、删除统计学时
c#·用户界面
技术拾荒者20 小时前
.net core mvc 控制器中页面跳转
后端·c#·asp.net·mvc·.netcore