观察者模式

一、概念

观察者模式是使用频率较高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,当一个对象发生改变时将自动通知其他对象,其他对象将做出相应的反应。在观察者模式中发生改变的对象称为观察目标,而被通知的对象成为观察者,一个观察者目标可以对应多个观察者。

定义:定义对象之间的一种一对多的依赖关系,使得每当一个对象状态发生改变时其相关依赖对象皆得到通知并自动更新。

二、模式结构

  • Subject(目标):被观察的对象,在目标定义一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify()。

  • Concrete Subject(具体目标):是目标的具体实现类,它维护着观察者列表,并在状态发生改变时通知观察者。

  • Observer(观察者):是接受目标通知的对象,定义了一个更新方法,当收到目标通知时,调用更新方法进行更新操作。

  • Concrete Observer(具体观察者):观察者的具体实现类,实现了更新方法,定义了在收到通知时需要执行的具体通知。

    image-20240709231123008

三、模式实现

// 目标类
public abstract class Subject
{
    protected List<Observer> observers = new List<Observer>();

    public void AddObserver(Observer observer)
    {
        observers.Add(observer);
    }

    public void RemoveObserver(Observer observer)
    {
        observers.Remove(observer);
    }

    public abstract void Notify();
}
// 具体目标类
public class ConcreteSubject : Subject
{
    public override void Notify()
    {
        foreach (var obs in observers)
        {
            obs.Update();
        }
    }
}
// 观察者类
public abstract class Observer
{
    public abstract void Update();
}
// 具体观察者类
public class ConcreteObserver : Observer
{
    public override void Update()
    {
        // 具体响应代码
    }
}

四、优缺点

  • 优点:
    1. 降低耦合度:将表示层与数据逻辑层分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样的表示层充当具体观察角色。
    2. 广播通信:观察目标会将所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
    3. 符合开闭原则:增加新的具体观察者无须修改原有系统代码,在具体观察者与观察者目标不存在联系关系。
  • 缺点:
    1. 性能消耗:如果一个观察目标有很多直接或者间接观察者时,所有的观察者都会通知到,而且如果观察目标状态不断发生改变,会一直通知调用,会很消耗性能。
    2. 死循环:如果观察者与观察目标之间存在循环依赖,可能会导致系统崩溃。

五、适用场景

  1. 事件系统/通知系统:当一个对象的状态发生变化时,需要通知其他对象。
  2. 发布-订阅:观察者模式是发布-订阅模型的一种实现方式。发布者(被观察者)发布消息,订阅者(观察者)接收并处理消息。