.NET 设计模式—观察者模式(Observer Pattern)

简介

在.NET中,观察者模式是一种设计模式,它允许对象之间进行一对多的依赖关系。当一个对象的状态发生变化时,所有依赖于它的对象都会收到通知并自动更新。这种模式在事件驱动的设计中非常常见。

在.NET中实现观察者模式,通常涉及到定义一个抽象的观察者接口和一个可被观察的对象。这个可被观察的对象维护一个观察者的列表,并在状态改变时通知所有观察者。

角色

  • 抽象主题角色(Subject):抽象主题把所有观察者对象的引用保存在一个列表中,并提供增加和删除观察者对象的操作,抽象主题角色又叫做抽象被观察者角色,一般由抽象类或接口实现。
  • 抽象观察者角色(Observer):为所有具体观察者定义一个接口,在得到主题通知时更新自己,一般由抽象类或接口实现。
  • 具体主题角色(ConcreteSubject):实现抽象主题接口,具体主题角色又叫做具体被观察者角色。
  • 具体观察者角色(ConcreteObserver):实现抽象观察者角色所要求的接口,以便使自身状态与主题的状态相协调。

优点

  • 观察者模式实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层,即观察者。
  • 观察者模式在被观察者和观察者之间建立了一个抽象的耦合,被观察者并不知道任何一个具体的观察者,只是保存着抽象观察者的列表,每个具体观察者都符合一个抽象观察者的接口。
  • 观察者模式支持广播通信。被观察者会向所有的注册过的观察者发出通知。

缺点

  • 如果一个被观察者有很多直接和间接的观察者时,将所有的观察者都通知到会花费很多时间。
  • 虽然观察者模式可以随时使观察者知道所观察的对象发送了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎样发生变化的。
  • 如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃,在使用观察者模式应特别注意这点。

应用场景

  • 当需要将一个对象的状态变化通知给其他多个对象时,可以使用观察者模式;
  • 当一个对象的改变需要同时改变其他对象的状态或者操作时,可以使用观察者模式;
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面时,可以使用观察者模式。例如,模型和视图之间的关系,模型驱动视图的更新,而视图反过来也要反映到模型中;
  • 当一个对象必须通知其他对象,但是你不知道这些对象是谁时,可以使用观察者模式。例如,你不知道哪些用户订阅了你的微信公众号,但你需要在每次发布新文章时通知所有订阅用户;
  • 当一个对象需要有别的对象来协助完成某项工作,并且不希望知道具体协助它的对象时,可以使用观察者模式。例如,一个员工完成某项任务需要得到经理的批准,但他并不知道具体是哪个经理会批准。

实现

  • 定义观察者接口
cs 复制代码
public interface IObserver
{
    void Update(string message); // 或者根据具体需求定义其他方法
}
  • 定义可观察的对象,它包含一个观察者列表,并提供注册和通知观察者的方法
cs 复制代码
using System.Collections.Generic;
 
public class Observable
{
    private List<IObserver> observers = new List<IObserver>();
    private string state;
 
    // 注册观察者
    public void RegisterObserver(IObserver observer)
    {
        observers.Add(observer);
    }
 
    // 移除观察者(可选)
    public void RemoveObserver(IObserver observer)
    {
        observers.Remove(observer);
    }
 
    // 通知所有观察者(状态改变时调用)
    protected void NotifyObservers(string message)
    {
        foreach (var observer in observers)
        {
            observer.Update(message);
        }
    }
 
    // 改变状态并通知观察者(这里假设状态是一个字符串)
    public void ChangeState(string newState)
    {
        state = newState;
        NotifyObservers("State changed to: " + state); // 通知所有观察者状态已改变及新状态信息
    }
}
  • 实现具体的观察者类,它实现观察者接口并定义如何响应通知
cs 复制代码
public class ConcreteObserver : IObserver
{
    public void Update(string message)
    {
        // 在这里处理接收到的通知,比如更新UI、记录日志等操作。
        Console.WriteLine("Observer received: " + message); // 仅作为示例,实际实现根据需求来定。
    }
}
  • 上层应用调用
cs 复制代码
class Program
{
    static void Main(string[] args)
    {
        // 创建可观察对象和观察者实例。
        Observable observable = new Observable();
        ConcreteObserver observer = new ConcreteObserver(); // 可以创建多个观察者实例。
        observable.RegisterObserver(observer); // 注册观察者到可观察对象。
        // ... 在程序的其他部分,当需要通知观察者时调用可观察对象的ChangeState方法     
        observable.ChangeState("New state information");。这样就会触发通知所有注册的观察者。
    }
}
相关推荐
触底反弹7 小时前
🤯 面试被问 AI Workflow 和 Agent 有啥区别?3 张图 + 2 段代码讲清楚!
人工智能·设计模式·面试
杨充1 天前
10.可测试性实战设计
设计模式·开源·代码规范
杨充1 天前
9.重构十二式的实战
设计模式·开源·代码规范
杨充1 天前
6.设计原则的全景图
设计模式·开源·全栈
杨充1 天前
2.面向对象的特性
设计模式
杨充1 天前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充1 天前
8.反模式与坏味道
设计模式·开源·代码规范
杨充1 天前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法