C# 观察者模式

本文介绍了观察者模式在C#中的应用,包括使用IObservable和IObserver接口、Subject类,以及如何通过事件和委托实现。通过实例演示了如何创建观察者和被观察者,以及如何管理他们的订阅和通知过程,强调了模式在提高代码灵活性和可维护性方面的优势。
摘要由CSDN通过智能技术生成

观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。

当主题对象状态发生改变时,它的所有依赖者(观察者)都会自动收到通知并更新。

一、在 C# 中实现观察者模式通常涉及以下关键部分

  1. IObservable<T> 和 IObserver<T> 接口

    • .NET Framework 提供了 System.IObservable<T> 和 System.IObserver<T> 两个接口来标准化观察者模式的实现。IObservable<T> 表示可发送通知的对象,而 IObserver<T> 定义了接收这些通知的方法。
    • IObserver<T> 接口中包含三个方法:OnNext(T value)OnError(Exception error) 和 OnCompleted(),分别用于接收到新的数据项、错误通知以及通知序列已完成。
  2. Subject 类

    • 往往会创建一个继承自 IObservable<T> 并实现其逻辑的类,比如 Subject<T> 或 ReplaySubject<T>(Rx.NET 库中),这个类负责维护订阅它的观察者的列表,并在适当的时候调用它们的方法。
  3. 观察者实现

    • 观察者类需要实现 IObserver<T> 接口,这样当被观察者有状态变化时,可以通过 OnNext 等方法得到通知并执行相应的操作。
  4. 注册与解除注册

    • 被观察者提供一个方法(如 Subscribe(IObserver<T> observer))让观察者可以订阅事件,同时应有一个方法(如 Unsubscribe(IObserver<T> observer) 或使用返回的 IDisposable 对象来取消订阅)来解除订阅。
  5. 事件委托和EventHandler

    • 在传统的 .NET 事件处理机制中,虽然不直接采用 IObservable/IObserver 接口,但观察者模式的概念体现在事件(Event)和委托(Delegate)上,其中 EventHandler<TEventArgs> 委托常用于表示事件处理程序,sender 参数扮演着被观察者角色,而 EventArgs 子类传递的状态信息则类似于通知的数据项。
  6. 实例教程步骤概要

    • 抽象出一个通知接口(或者直接使用现有框架提供的 Observable 接口)。
    • 观察者实现该接口以接收通知。
    • 被观察者维护一个观察者集合,并提供注册/取消注册的方法。
    • 当被观察者状态变化时,遍历观察者集合并调用它们的更新方法,从而触发所有观察者的响应。

二、使用接口简单实现观察者模式

使用时,订阅者会注册到发布者的观察者列表中,当发布者发布新数据时,所有已注册的订阅者都会收到通知并执行相应操作。

// 定义通知接口(也可以使用现有的 INotifyPropertyChanged, IObservable<T>)
public interface INotification
{
    void Notify(string message);
}

// 被观察者实现
public class Publisher : INotification
{
    private List<IObserver<string>> _observers = new List<IObserver<string>>();

    public void RegisterObserver(IObserver<string> observer)
    {
        _observers.Add(observer);
    }

    public void UnregisterObserver(IObserver<string> observer)
    {
        _observers.Remove(observer);
    }

    public void PublishNewData(string data)
    {
        foreach (var observer in _observers)
        {
            observer.OnNext(data);
        }
    }
}

// 观察者实现
public class Subscriber : IObserver<string>
{
    public void OnNext(string value)
    {
        Console.WriteLine($"Subscriber received: {value}");
    }

    public void OnError(Exception error)
    {
        // 处理错误
    }

    public void OnCompleted()
    {
        // 清理或完成相关工作
    }
}

 

 

三、使用事件(Event)和委托(Delegate)来实现观察者模式

C# delegate的使用

 

定义一个被观察的主题Subject

using System;  
using System.Collections.Generic;  
  
public class Subject  
{  
    // 委托类型,表示观察者的行为  
    public delegate void StateChangedHandler(string newState);  
      
    // 事件,用于注册和注销观察者  
    public event StateChangedHandler StateChanged;  
      
    // 主题的状态  
    private string _state;  
      
    // 获取或设置主题的状态  
    public string State  
    {  
        get => _state;  
        set  
        {  
            _state = value;  
            // 当状态改变时,通知所有观察者  
            OnStateChanged();  
        }  
    }  
      
    // 受保护的方法,用于触发事件  
    protected virtual void OnStateChanged()  
    {  
        StateChanged?.Invoke(_state);  
    }  
      
    // 订阅事件的方法  
    public void Subscribe(StateChangedHandler handler)  
    {  
        StateChanged += handler;  
    }  
      
    // 取消订阅事件的方法  
    public void Unsubscribe(StateChangedHandler handler)  
    {  
        StateChanged -= handler;  
    }  
}

定义观察者Observer

public class Observer  
{  
    private string _name;  
    private Subject _subject;  
  
    public Observer(string name, Subject subject)  
    {  
        _name = name;  
        _subject = subject;  
        // 订阅主题的状态改变事件  
        _subject.Subscribe(HandleStateChanged);  
    }  
      
    private void HandleStateChanged(string newState)  
    {  
        Console.WriteLine($"Observer {_name} received new state: {newState}");  
    }  
}

使用这些类

class Program  
{  
    static void Main(string[] args)  
    {  
        // 创建主题  
        Subject subject = new Subject();  
          
        // 创建观察者并订阅主题事件  
        Observer observer1 = new Observer("Observer1", subject);  
        Observer observer2 = new Observer("Observer2", subject);  
          
        // 改变主题状态,触发事件  
        subject.State = "New State";  
          
        // 等待用户输入,防止程序立即退出  
        Console.ReadLine();  
    }  
}

在这个例子中,Subject类有一个State属性,当它的值改变时,它会触发一个事件。

Observer类在创建时订阅了这个事件,并定义了一个方法来处理这个事件。

SubjectState改变时,所有订阅了StateChanged事件的Observer对象都会收到通知,并调用它们自己的HandleStateChanged方法。

 

这就是观察者模式在C#中的基本实现。它允许主题和观察者之间保持松耦合,主题不需要知道具体有哪些观察者,而观察者也不需要知道主题的具体实现。

这提高了代码的可扩展性、可维护性和灵活性。

 

 

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个 C#观察者模式实例: ```csharp using System; using System.Collections.Generic; // 被观察者接口 interface ISubject { void Attach(IObserver observer); // 添加观察者 void Detach(IObserver observer); // 移除观察者 void Notify(); // 通知观察者 } // 观察者接口 interface IObserver { void Update(ISubject subject); // 接收通知并更新 } // 具体的被观察者类 class ConcreteSubject : ISubject { private List<IObserver> observers = new List<IObserver>(); private string state; // 被观察者状态 // 添加观察者 public void Attach(IObserver observer) { observers.Add(observer); } // 移除观察者 public void Detach(IObserver observer) { observers.Remove(observer); } // 通知观察者 public void Notify() { foreach (IObserver observer in observers) { observer.Update(this); } } // 修改状态并通知观察者 public void SetState(string state) { this.state = state; Notify(); } public string GetState() { return state; } } // 具体的观察者类 class ConcreteObserver : IObserver { private string name; // 观察者名称 public ConcreteObserver(string name) { this.name = name; } // 接收通知并更新 public void Update(ISubject subject) { Console.WriteLine("{0} 接收到了被观察者的通知,当前状态为 {1}", name, ((ConcreteSubject)subject).GetState()); } } // 测试代码 class Program { static void Main(string[] args) { ConcreteSubject subject = new ConcreteSubject(); // 添加观察者 subject.Attach(new ConcreteObserver("观察者 A")); subject.Attach(new ConcreteObserver("观察者 B")); subject.Attach(new ConcreteObserver("观察者 C")); // 修改状态并通知观察者 subject.SetState("状态 1"); // 移除观察者 subject.Detach(new ConcreteObserver("观察者 B")); // 修改状态并通知观察者 subject.SetState("状态 2"); Console.ReadKey(); } } ``` 以上代码实现了一个简单的观察者模式实例,其中 `ConcreteSubject` 是具体的被观察者类,实现了 `ISubject` 接口;`ConcreteObserver` 是具体的观察者类,实现了 `IObserver` 接口。在测试代码中,我们创建了一个 `ConcreteSubject` 对象,并添加了三个观察者,然后修改了状态并通知观察者,最后移除了一个观察者并再次修改状态并通知观察者。运行该程序,控制台输出如下: ``` 观察者 A 接收到了被观察者的通知,当前状态为 状态 1 观察者 B 接收到了被观察者的通知,当前状态为 状态 1 观察者 C 接收到了被观察者的通知,当前状态为 状态 1 观察者 A 接收到了被观察者的通知,当前状态为 状态 2 观察者 C 接收到了被观察者的通知,当前状态为 状态 2 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wangnaisheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值