跳转到主内容
极星编程网:以代码为星,赴技术山海!

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

C#中实现观察者模式的核心是定义主题与观察者,通过接口、事件或IObservable方式实现状态变更时的自动通知,适用于事件驱动场景。 在 C# 中实现观察者模式,核心是定义一个被观察对象(主题)和多个观察者,当主题状态发生变化时,自动通知所有注册的观察者。这种设计模式非常适合处理事件驱动的场景,比如 UI 更新、消息广播等。 观察者模式的基本结构 观察者模式包含两个主要角色: Subject(主题) :维护观察者列表,提供注册、注销和通知方法。 Observer(观察者) :实现一个更新接口,用于接收主题的通知。 在 C# 中,可以通过接口和委托两种方式来实现。下面分别介绍具体做法。 使用接口手动实现观察者模式 定义观察者和主题接口,让具体类实现它们。 示例代码:
// 观察者接口 public interface IObserver { void Update(string message); }

// 主题接口 public interface ISubject { void Attach(IObserver observer); void Detach(IObserver observer); void Notify(string message); }

// 具体主题 public class NewsAgency : ISubject { private List _observers = new List();

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("凤凰");

agency.Attach(channelA); agency.Attach(channelB);

agency.PublishNews("今日天气晴朗");

// 输出: // 新闻机构发布:今日天气晴朗 // 央视 收到新闻:今日天气晴朗 // 凤凰 收到新闻:今日天气晴朗

利用 C# 委托和事件简化实现 C# 的事件机制天生适合观察者模式。通过 event 和 delegate ,可以更简洁地实现松耦合通信。 示例代码:
public class Stock { // 定义委托 public delegate void PriceChangedHandler(string symbol, double price);
// 定义事件
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);
}
} 观察者订阅事件: C函数速查手册(CHM版) C函数速查手册(CHM版) 下载
var stock = new Stock("AAPL", 150.0);

// 订阅事件 stock.PriceChanged += (symbol, price) => { Console.WriteLine($"股票 {symbol} 价格变更为:{price}"); };

stock.Price = 155.0; // 输出:股票 AAPL 价格变更为:155

这种方式更符合 C# 的编程习惯,代码更简洁,且线程安全由语言机制部分保障。 使用 IObservable 和 IObserver 接口(响应式扩展) C# 还提供了内置的 IObservable 和 IObserver 接口,属于 .NET 的响应式扩展(Reactive Extensions, Rx),适用于更复杂的异步数据流场景。
public class Sensor : IObservable { private List> _observers = new List>();
public IDisposable Subscribe(IObserver 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> _observers;
    private IObserver _observer;

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

    public void Dispose()
    {
        _observers.Remove(_observer);
    }
}
} 使用方式:
var sensor = new Sensor();

var observer = new MyObserver(); var subscription = sensor.Subscribe(observer);

sensor.Measure(23.5); // 触发通知

subscription.Dispose(); // 取消订阅

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

相关文章