设计模式 19 观察者模式

设计模式 19

  • 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
  • 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

文章目录

  • [设计模式 19](#设计模式 19)
    • [观察者模式(Observer Pattern)](#观察者模式(Observer Pattern))
      • [1 定义](#1 定义)
      • [2 结构](#2 结构)
      • [3 示例代码](#3 示例代码)
      • [4 特点](#4 特点)
      • [5 适用场景](#5 适用场景)
      • [6 总结](#6 总结)

观察者模式(Observer Pattern)

1 定义

观察者模式的核心思想是当一个对象(被观察者)的状态改变时,所有依赖于它的对象(观察者)都会被通知并更新。这样一来,观察者模式实现了对象之间的松散耦合,使得一个对象的变化可以自动地传播到相关的对象。

2 结构

观察者模式包含以下角色:

  • 主题(Subject): 被观察的对象,维护着一组观察者对象的引用,提供注册、移除观察者的接口,并在状态发生变化时通知所有观察者。
  • 观察者(Observer): 定义一个更新接口,当收到通知时进行相应的更新操作。
  • 具体主题(ConcreteSubject): 具体的被观察对象,通常包含状态,当状态发生变化时,通知所有已注册的观察者。
  • 具体观察者(ConcreteObserver): 实现观察者接口,负责在状态变化时更新自身。

UML 类图

scss 复制代码
+---------------------------+         +-------------------+
|     Subject               | <------ |     Observer      |
+---------------------------+         +-------------------+
| + Attach(obs: Observer)   |         | + Update(): void  |
| + Detach(obs: Observer)   |         +-------------------+
| + Notify(): void          |               ^
+---------------------------+               |
        ^                                   |
        |                                   |
+-----------------------+             +-------------------+
| ConcreteSubject       |             | ConcreteObserver  |
+-----------------------+             +-------------------+
| - state: State        |             | - state: State    |
| + GetState(): State   |             | + Update(): void  |
| + SetState(State)     |             +-------------------+
+-----------------------+

3 示例代码

假设我们要实现一个天气站系统,天气站会记录当前的天气信息,并通知注册的显示设备(如手机应用、网站等)进行更新。

观察者接口

csharp 复制代码
// 观察者接口
public interface IObserver
{
    void Update(string temperature, string humidity, string pressure);
}

主题接口

csharp 复制代码
// 主题接口
public interface ISubject
{
    void RegisterObserver(IObserver observer);
    void RemoveObserver(IObserver observer);
    void NotifyObservers();
}

具体主题

csharp 复制代码
// 具体主题
public class WeatherStation : ISubject
{
    private List<IObserver> _observers;
    private string _temperature;
    private string _humidity;
    private string _pressure;

    public WeatherStation()
    {
        _observers = new List<IObserver>();
    }

    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(_temperature, _humidity, _pressure);
        }
    }

    public void SetMeasurements(string temperature, string humidity, string pressure)
    {
        _temperature = temperature;
        _humidity = humidity;
        _pressure = pressure;
        NotifyObservers();
    }
}

具体观察者

csharp 复制代码
// 具体观察者
public class PhoneDisplay : IObserver
{
    private string _temperature;
    private string _humidity;
    private string _pressure;

    public void Update(string temperature, string humidity, string pressure)
    {
        _temperature = temperature;
        _humidity = humidity;
        _pressure = pressure;
        Display();
    }

    public void Display()
    {
        Console.WriteLine($"Phone Display -> Temperature: {_temperature}, Humidity: {_humidity}, Pressure: {_pressure}");
    }
}

public class WebDisplay : IObserver
{
    private string _temperature;
    private string _humidity;
    private string _pressure;

    public void Update(string temperature, string humidity, string pressure)
    {
        _temperature = temperature;
        _humidity = humidity;
        _pressure = pressure;
        Display();
    }

    public void Display()
    {
        Console.WriteLine($"Web Display -> Temperature: {_temperature}, Humidity: {_humidity}, Pressure: {_pressure}");
    }
}

客户端代码

csharp 复制代码
class Program
{
    static void Main(string[] args)
    {
        WeatherStation weatherStation = new WeatherStation();

        IObserver phoneDisplay = new PhoneDisplay();
        IObserver webDisplay = new WebDisplay();

        weatherStation.RegisterObserver(phoneDisplay);
        weatherStation.RegisterObserver(webDisplay);

        weatherStation.SetMeasurements("30°C", "65%", "1013 hPa");

        weatherStation.RemoveObserver(phoneDisplay);

        weatherStation.SetMeasurements("28°C", "70%", "1012 hPa");
    }
}

运行结果

plaintext 复制代码
Phone Display -> Temperature: 30°C, Humidity: 65%, Pressure: 1013 hPa
Web Display -> Temperature: 30°C, Humidity: 65%, Pressure: 1013 hPa
Web Display -> Temperature: 28°C, Humidity: 70%, Pressure: 1012 hPa

在这个例子中,WeatherStation 是具体的主题,当天气数据发生变化时,它通知所有注册的观察者(如 PhoneDisplayWebDisplay)进行更新并显示新的数据。

4 特点

  • 优点:

    • 松散耦合: 观察者和主题之间是松散耦合的,观察者可以独立于主题的变化而变化,增加了系统的灵活性。

    • 动态更新: 观察者模式使得对象之间的通信更加灵活,可以动态添加或删除观察者,实时更新数据。

    • 符合开放-封闭原则: 可以在不修改现有代码的情况下,增加新的观察者。

  • 缺点:

    • 通知开销: 如果有大量的观察者,通知所有观察者可能会引起开销,影响性能。

    • 可能出现循环依赖: 如果观察者之间也相互依赖,可能会导致循环依赖问题,影响系统的稳定性。

5 适用场景

  • 事件处理系统: 当需要对某个事件发生时,触发多个对象的响应时,观察者模式非常适用。
  • 数据模型与视图同步: 在模型-视图架构中,当模型的数据变化时,需要通知视图更新显示,可以使用观察者模式。
  • 广播通信: 当一个对象的状态改变需要通知多个对象时,可以使用观察者模式。

6 总结

观察者模式通过定义一对多的依赖关系,实现了对象间的松散耦合和动态通信。它允许对象自动通知相关的依赖对象并更新状态,非常适合用于事件驱动的系统和需要动态更新的场景。尽管可能会带来一定的通知开销和复杂性管理,但它依然是实现对象间动态通信的强大工具。

相关推荐
小白不太白9504 分钟前
设计模式之 责任链模式
python·设计模式·责任链模式
吾与谁归in33 分钟前
【C#设计模式(13)——代理模式(Proxy Pattern)】
设计模式·c#·代理模式
吾与谁归in34 分钟前
【C#设计模式(14)——责任链模式( Chain-of-responsibility Pattern)】
设计模式·c#·责任链模式
闲人一枚(学习中)42 分钟前
设计模式-创建型-原型模式
设计模式
蓝田~1 小时前
观察者模式和订阅模式
windows·观察者模式
Iced_Sheep1 小时前
干掉 if else 之策略模式
后端·设计模式
哪 吒9 小时前
最简单的设计模式,抽象工厂模式,是否属于过度设计?
设计模式·抽象工厂模式
Theodore_10229 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
转世成为计算机大神12 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
小乖兽技术13 小时前
23种设计模式速记法
设计模式