C# 设计模式--观察者模式 (Observer Pattern)
定义
观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。观察者模式的核心在于解耦主题(被观察者)和观察者之间的依赖关系。
正确写法
假设我们有一个天气预报系统,当天气变化时,需要通知多个订阅者(如手机应用、网站等)。
using System;
using System.Collections.Generic;
// 被观察者接口
public interface ISubject
{
void RegisterObserver(IObserver observer);
void RemoveObserver(IObserver observer);
void NotifyObservers();
}
// 观察者接口
public interface IObserver
{
void Update(string weatherInfo);
}
// 具体被观察者
public class WeatherStation : ISubject
{
private List<IObserver> observers = new List<IObserver>();
private string weatherInfo;
public void SetWeatherInfo(string info)
{
this.weatherInfo = info;
NotifyObservers();
}
public void RegisterObserver(IObserver observer)
{
observers.Add(observer);
}
public void RemoveObserver(IObserver observer)
{
observers.Remove(observer);
}
public void NotifyObservers()
{
foreach (var observer in observers)
{
observer.Update(weatherInfo);
}
}
}
// 具体观察者
public class MobileApp : IObserver
{
public void Update(string weatherInfo)
{
Console.WriteLine($"Mobile App received: {weatherInfo}");
}
}
public class Website : IObserver
{
public void Update(string weatherInfo)
{
Console.WriteLine($"Website received: {weatherInfo}");
}
}
// 客户端代码
class Program
{
static void Main(string[] args)
{
WeatherStation weatherStation = new WeatherStation();
IObserver mobileApp = new MobileApp();
IObserver website = new Website();
weatherStation.RegisterObserver(mobileApp);
weatherStation.RegisterObserver(website);
weatherStation.SetWeatherInfo("Sunny and warm");
weatherStation.RemoveObserver(mobileApp);
weatherStation.SetWeatherInfo("Cloudy with a chance of rain");
}
}
类图:
解释
- 被观察者接口 (
ISubject
):定义了注册、移除和通知观察者的方法。 - 观察者接口 (
IObserver
):定义了更新方法,当被观察者状态改变时,观察者会收到通知。 - 具体被观察者 (
WeatherStation
):实现了ISubject
接口,管理观察者的注册、移除和通知。 - 具体观察者 (
MobileApp
和Website
):实现了IObserver
接口,接收被观察者的通知并进行相应的处理。 - 客户端代码 (
Program
):创建了WeatherStation
实例,并注册了MobileApp
和Website
作为观察者。通过调用SetWeatherInfo
方法改变天气信息,触发观察者的更新方法。之后移除MobileApp
观察者,并再次改变天气信息,验证观察者机制。
用途
- 解耦主题和观察者:观察者模式使得主题和观察者之间的依赖关系变得松散,主题不需要知道观察者的具体实现。
- 动态注册和注销:观察者可以动态地注册和注销,使得系统更加灵活。
- 事件驱动:适用于事件驱动的系统,当某个事件发生时,可以通知多个观察者进行相应的处理。
优点
- 解耦:主题和观察者之间的依赖关系被解耦,使得代码更加灵活和可维护。
- 扩展性:增加新的观察者时,不需要修改主题的代码,符合开闭原则。
- 动态性:观察者可以动态地注册和注销,使得系统更加灵活。
缺点
- 性能问题:如果观察者数量较多,通知所有观察者可能会导致性能问题。
- 内存泄漏:如果观察者没有正确注销,可能会导致内存泄漏。
- 调试困难:由于观察者模式涉及多个对象之间的交互,调试时可能会比较困难。
适用场景
- 事件驱动系统:当需要在某个事件发生时通知多个对象时。
- 解耦对象:当需要解耦主题和观察者之间的依赖关系时。
- 动态注册和注销:当观察者需要动态地注册和注销时。
实际开发中的应用
1. 消息通知系统
假设我们正在开发一个消息通知系统,当用户发布新消息时,需要通知多个订阅者(如邮件、短信、推送通知等)。
using System;
using System.Collections.Generic;
// 被观察者接口
public interface IMessagePublisher
{
void RegisterSubscriber(IMessageSubscriber subscriber);
void UnregisterSubscriber(IMessageSubscriber subscriber);
void NotifySubscribers(string message);
}
// 观察者接口
public interface IMessageSubscriber
{
void OnMessageReceived(string message);
}
// 具体被观察者
public class MessagePublisher : IMessagePublisher
{
private List<IMessageSubscriber> subscribers = new List<IMessageSubscriber>();
public void PublishMessage(string message)
{
NotifySubscribers(message);
}
public void RegisterSubscriber(IMessageSubscriber subscriber)
{
subscribers.Add(subscriber);
}
public void UnregisterSubscriber(IMessageSubscriber subscriber)
{
subscribers.Remove(subscriber);
}
public void NotifySubscribers(string message)
{
foreach (var subscriber in subscribers)
{
subscriber.OnMessageReceived(message);
}
}
}
// 具体观察者
public class EmailSubscriber : IMessageSubscriber
{
public void OnMessageReceived(string message)
{
Console.WriteLine($"Email received: {message}");
}
}
public class SMS Subscriber : IMessageSubscriber
{
public void OnMessageReceived(string message)
{
Console.WriteLine($"SMS received: {message}");
}
}
public class PushNotificationSubscriber : IMessageSubscriber
{
public void OnMessageReceived(string message)
{
Console.WriteLine($"Push notification received: {message}");
}
}
// 客户端代码
class Program
{
static void Main(string[] args)
{
MessagePublisher publisher = new MessagePublisher();
IMessageSubscriber emailSubscriber = new EmailSubscriber();
IMessageSubscriber smsSubscriber = new SMS Subscriber();
IMessageSubscriber pushNotificationSubscriber = new PushNotificationSubscriber();
publisher.RegisterSubscriber(emailSubscriber);
publisher.RegisterSubscriber(smsSubscriber);
publisher.RegisterSubscriber(pushNotificationSubscriber);
publisher.PublishMessage("New message: Hello, world!");
publisher.UnregisterSubscriber(emailSubscriber);
publisher.PublishMessage("Another message: Goodbye, world!");
}
}
2. 股票市场监控
假设我们正在开发一个股票市场监控系统,当股票价格发生变化时,需要通知多个订阅者(如投资者、分析师等)。
```csharp
using System;
using System.Collections.Generic;
// 被观察者接口
public interface IStockMarket
{
void RegisterInvestor(IInvestor investor);
void UnregisterInvestor(IInvestor investor);
void NotifyInvestors(string stockInfo);
}
// 观察者接口
public interface IInvestor
{
void OnStockPriceChange(string stockInfo);
}
// 具体被观察者
public class StockMarket : IStockMarket
{
private List<IInvestor> investors = new List<IInvestor>();
public void UpdateStockPrice(string stockInfo)
{
NotifyInvestors(stockInfo);
}
public void RegisterInvestor(IInvestor investor)
{
investors.Add(investor);
}
public void UnregisterInvestor(IInvestor investor)
{
investors.Remove(investor);
}
public void NotifyInvestors(string stockInfo)
{
foreach (var investor in investors)
{
investor.OnStockPriceChange(stockInfo);
}
}
}
// 具体观察者
public class IndividualInvestor : IInvestor
{
public void OnStockPriceChange(string stockInfo)
{
Console.WriteLine($"Individual Investor received: {stockInfo}");
}
}
public class InstitutionalInvestor : IInvestor
{
public void OnStockPriceChange(string stockInfo)
{
Console.WriteLine($"Institutional Investor received: {stockInfo}");
}
}
public class Analyst : IInvestor
{
public void OnStockPriceChange(string stockInfo)
{
Console.WriteLine($"Analyst received: {stockInfo}");
}
}
// 客户端代码
class Program
{
static void Main(string[] args)
{
StockMarket market = new StockMarket();
IInvestor individualInvestor = new IndividualInvestor();
IInvestor institutionalInvestor = new InstitutionalInvestor();
IInvestor analyst = new Analyst();
market.RegisterInvestor(individualInvestor);
market.RegisterInvestor(institutionalInvestor);
market.RegisterInvestor(analyst);
market.UpdateStockPrice("Apple stock price increased by 5%");
market.UnregisterInvestor(individualInvestor);
market.UpdateStockPrice("Google stock price decreased by 2%");
}
}
总结
观察者模式通过定义对象之间的一对多依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。虽然它可能会带来一些性能和调试上的问题,但在需要解耦主题和观察者、支持动态注册和注销的场景中,观察者模式能够显著提高代码的可维护性和扩展性。
原文地址:https://blog.csdn.net/qq_15355867/article/details/144190448
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!