自学内容网 自学内容网

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
+void RegisterObserver(IObserver observer)
+void RemoveObserver(IObserver observer)
+void NotifyObservers()
IObserver
+void Update(string weatherInfo)
WeatherStation
-List observers
-string weatherInfo
+void SetWeatherInfo(string info)
+void RegisterObserver(IObserver observer)
+void RemoveObserver(IObserver observer)
+void NotifyObservers()
MobileApp
+void Update(string weatherInfo)
Website
+void Update(string weatherInfo)
Program
+static void Main(string[] args)

解释

  1. 被观察者接口 (ISubject):定义了注册、移除和通知观察者的方法。
  2. 观察者接口 (IObserver):定义了更新方法,当被观察者状态改变时,观察者会收到通知。
  3. 具体被观察者 (WeatherStation):实现了 ISubject 接口,管理观察者的注册、移除和通知。
  4. 具体观察者 (MobileAppWebsite):实现了 IObserver 接口,接收被观察者的通知并进行相应的处理。
  5. 客户端代码 (Program):创建了 WeatherStation 实例,并注册了 MobileAppWebsite 作为观察者。通过调用 SetWeatherInfo 方法改变天气信息,触发观察者的更新方法。之后移除 MobileApp 观察者,并再次改变天气信息,验证观察者机制。

用途

  1. 解耦主题和观察者:观察者模式使得主题和观察者之间的依赖关系变得松散,主题不需要知道观察者的具体实现。
  2. 动态注册和注销:观察者可以动态地注册和注销,使得系统更加灵活。
  3. 事件驱动:适用于事件驱动的系统,当某个事件发生时,可以通知多个观察者进行相应的处理。

优点

  1. 解耦:主题和观察者之间的依赖关系被解耦,使得代码更加灵活和可维护。
  2. 扩展性:增加新的观察者时,不需要修改主题的代码,符合开闭原则。
  3. 动态性:观察者可以动态地注册和注销,使得系统更加灵活。

缺点

  1. 性能问题:如果观察者数量较多,通知所有观察者可能会导致性能问题。
  2. 内存泄漏:如果观察者没有正确注销,可能会导致内存泄漏。
  3. 调试困难:由于观察者模式涉及多个对象之间的交互,调试时可能会比较困难。

适用场景

  1. 事件驱动系统:当需要在某个事件发生时通知多个对象时。
  2. 解耦对象:当需要解耦主题和观察者之间的依赖关系时。
  3. 动态注册和注销:当观察者需要动态地注册和注销时。
    实际开发中的应用

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)!