观察者模式
概念
观察者设计模式是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
典型案例
- C# 中的委托和事件
参考链接:观察者设计模式(C#委托和事件的使用)
委托和事件在观察者设计模式中的角色
- 委托:
委托是一种类型安全的函数指针,它允许将方法作为参数传递给其他方法。在观察者设计模式中,委托通常用于定义观察者需要响应的事件类型。
委托可以看作是对函数的抽象,它允许将多个方法绑定到同一个委托实例上,并在需要时依次调用这些方法。 - 事件:
事件是委托的一种特殊应用,它是对委托的进一步封装,提供了更高级别的抽象和封装性。
在观察者设计模式中,事件用于在被观察者(Subject)中声明,当被观察者的状态发生变化时,通过触发事件来通知所有注册的观察者(Observer)。
事件具有注册(+=)和注销(-=)机制,允许观察者动态地订阅和取消订阅事件。
相关代码:
/// <summary>
/// 观察者
/// </summary>
public class Mouse
{
private readonly string _name;
private readonly string _color;
public Mouse(string name, string color)
{
_name = name;
_color = color;
}
public void MouseRun()
{
Console.WriteLine("名字为:" + _name + "的老鼠开始逃跑了");
}
}
/// <summary>
/// 被观察者
/// </summary>
public class Cat
{
private readonly string _name;
private readonly string _color;
public delegate void MyDelegate();
private event MyDelegate CatComeEventHandler;
public Cat(string name, string color, Mouse mouse)
{
this._name = name;
this._color = color;
// 注册事件,将事件指向mouse.MouseRun方法
this.CatComeEventHandler += mouse.MouseRun;
}
public void CatCome()
{
Console.WriteLine("名字为:" + _name + "的小猫叫了一声");
//利用事件调用被注册的方法。CatCome事件发生,被注册的事件也发生。这就是观察者模式。
CatComeEventHandler();
}
}
//调用
static void Main(string[] args)
{
Mouse mouse = new("jim","white");
Cat cat = new("hh","black",mouse);
cat.CatCome();
Console.ReadKey();
}
// 在C# 中最典型的案例是 winform中的Button的Click事件,感兴趣的话可以去看一下源码。
// 这里是部分代码,注:相关源码代码细节比较多,这里就不一一示例了。
button1.Click += button1_Click;
// Click事件的相关源代码:
[SRCategory(nameof(SR.CatAction))]
[SRDescription(nameof(SR.ControlOnClickDescr))]
public event EventHandler? Click
{
// 添加事件
add => Events.AddHandler(s_clickEvent, value);
// 移除事件
remove => Events.RemoveHandler(s_clickEvent, value);
}
通信方式(防止弄混概念)
这里举两个例子来说明:
- 事件监听模式:通常以同步或异步的方式实现,但更多时候以同步方式为主。即当事件发生时,事件源会立即通知并调用所有注册的事件监听器的相应方法
– 应用实例:Web开发的交互事件:Button的click事件,例如Vue.js。 说句题外话: js不止是可以同步,其实还可以异步,众所周知,类似于Java、C++、C# 实现异步都是多线程语言,但是js这门编程语言本身就是单线程,那如何实现异步呢?在es6之后 有两个很重要的关键字:async
和await
,这两个关键字一般是在一起用,不然的话也没意义··· 它的本质是实现了Js中的promise,原理是:循环队列和事件循环(event loop)。注意 在这里要与C#
中的async
和await
的实现原理不一样,只是用到的关键字是一样的。 - 发布和订阅模式:主要使用异步通信方式。发布者将消息发送到消息队列或代理,订阅者从消息队列或代理中异步获取消息。这种异步通信方式提高了系统的可伸缩性和容错性。
- 发布和订阅模式最典型的相关协议莫过于:MQTT协议,包含发布者(Publisher)、订阅者(Subscriber)和消息队列或代理(Broker)。发布者发布消息到消息队列或代理,订阅者从消息队列或代理中订阅感兴趣的内容。 典型的一对多,解耦服务由消息队列或者Broker进行解耦。