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);
}
}
观察者订阅事件:
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 则适用于高级异步场景。选择哪种方式取决于项目复杂度和需求。










