观察者模式(Observer Pattern)

观察者模式(Observer Pattern)


定义

观察者模式(Observer Pattern)‌ 是一种行为设计模式,允许对象(称为 ‌Subject‌,主题)维护一组依赖对象(称为 ‌Observer‌,观察者),并在主题状态变化时自动通知所有观察者。其核心是 ‌一对多的依赖关系‌ 和 ‌事件驱动的通信机制‌

核心思想

  • 解耦主题与观察者‌:主题无需知道观察者的具体实现,只需通过接口通知。

  • 动态订阅机制‌:观察者可随时注册或注销对主题的监听。

  • 自动广播通知‌:主题状态变化时,自动触发所有观察者的响应逻辑。

模式结构

  • 抽象主题(Subject):定义注册、移除观察者的接口,维护观察者列表,在状态变化时触发通知。作为被观察对象的核心抽象,通过接口规范观察者管理行为。

  • 具体主题类(ConcreteSubject)‌:实现抽象主题接口,存储具体状态数据,状态变更时调用通知方法,是状态的实际持有者。

  • 观察者接口(IObserver)‌:定义接收主题通知的更新方法, 解耦主题与观察者的关键,确保观察者实现统一的更新逻辑。

  • 具体观察者类(ConcreteObserver)‌:实现观察者接口,定义自身对主题状态变化的响应逻辑(如更新显示、记录日志),实现业务场景中的具体响应。

主要解决的问题

  • 对象间实时更新‌:当对象状态变化时,依赖它的多个对象需同步更新(如 GUI 组件)。

  • 避免紧耦合‌:减少主题与观察者的直接依赖,提升代码复用性和扩展性

  • 替代轮询机制‌:通过事件驱动避免资源浪费,仅在状态变化时触发更新。

代码示例

场景描述

假设一个气象站(WeatherStation)作为主题,当温度变化时,自动通知显示屏(Display)和移动应用(MobileApp)更新显示。

‌实现代码

using System;
using System.Collections.Generic;

// 主题接口
interface ISubject
{
    void RegisterObserver(IObserver observer);
    void RemoveObserver(IObserver observer);
    void NotifyObservers();
}

// 观察者接口
interface IObserver
{
    void Update(float temperature);
}

// 具体主题:气象站
class WeatherStation : ISubject
{
    public event Action<float>? OnTemperatureChanged;
    private float _temperature;

    public void RegisterObserver(IObserver observer)
    {
        OnTemperatureChanged += observer.Update;
    }
    public void RemoveObserver(IObserver observer)
    {
        OnTemperatureChanged -= observer.Update;
    }
    public void NotifyObservers()
    {
        OnTemperatureChanged?.Invoke(Temperature);
    }
    public float Temperature
    {
        get => _temperature;
        set
        {
            _temperature = value;
            NotifyObservers(); // 温度变化时触发通知
        }
    }
}

// 具体观察者:显示屏
class Display : IObserver
{
    public void Update(float temperature) => 
        Console.WriteLine($"显示屏更新:当前温度 {temperature}°C");
}

// 具体观察者:移动应用
class MobileApp : IObserver
{
    public void Update(float temperature) => 
        Console.WriteLine($"移动应用推送:气温已变为 {temperature}°C");
}

// 客户端调用
class Program
{
    static void Main()
    {
        WeatherStation station = new WeatherStation();
        Display display = new Display();
        MobileApp app = new MobileApp();

        // 注册观察者
        station.RegisterObserver(display);
        station.RegisterObserver(app);

        // 模拟温度变化
        station.Temperature = 25.5f;
        station.Temperature = 26.0f;

        // 移除一个观察者
        station.RemoveObserver(app);
        station.Temperature = 27.3f;
    }
}

‌输出结果

显示屏更新:当前温度 25.5°C  
移动应用推送:气温已变为 25.5°C  
显示屏更新:当前温度 26°C  
移动应用推送:气温已变为 26°C  
显示屏更新:当前温度 27.3°C  

总结

‌优点

  • 解耦性强‌:主题与观察者通过接口交互,互不影响内部实现。

  • 动态扩展‌:新增观察者无需修改主题代码,符合开闭原则。

  • 事件驱动高效‌:仅在状态变化时触发更新,避免资源浪费。

‌缺点

  • 通知顺序不可控‌:观察者响应顺序可能影响系统行为。

  • 循环引用风险‌:若观察者持有主题引用且未正确注销,可能导致内存泄漏。

通过观察者模式,C# 开发者可以构建灵活、可维护的事件驱动系统,广泛应用于 GUI 框架、消息队列、实时数据同步等场景。

posted @ 2025-04-23 17:05  刘继先  阅读(79)  评论(0)    收藏  举报