发布-订阅模式

发布-订阅模式 (Publish-Subscribe Pattern)

发布-订阅模式是一种消息通信模式,它允许多个订阅者监听特定类型的消息,当消息发布时,所有订阅该类型的订阅者都会收到消息。这种模式通常用于异步通信和事件驱动的系统。

关键角色:

  1. Publisher(发布者) 发送消息的对象。
  2. Subscriber(订阅者) 接收消息的对象。
  3. Broker(中间人/事件总线) 管理发布者和订阅者之间的通信,可以是显式的也可以是隐式的。

这段代码展示了如何创建一个简单的 EventAggregator类,它允许发布和订阅泛型事件。在实际应用中可能需要更复杂的逻辑来处理线程安全、内存泄漏预防以及更精细的事件管理需求。不过,对于理解基本概念,这个示例应该足够了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 事件聚合器类,用于管理事件的订阅和发布
public class EventAggregator
{
// 存储事件名称与对应的操作列表的字典
private Dictionary<string, List<Action<string>>> _subscribers = new();
// 订阅事件
// eventName: 事件名称
// action: 订阅者需要执行的操作
public void Subscribe(string eventName, Action<string> action)
{
if (!_subscribers.ContainsKey(eventName))
{
_subscribers[eventName] = new List<Action<string>>();
}
_subscribers[eventName].Add(action);
}
// 取消订阅事件
public void Unsubscribe(string eventName, Action<string> action)
{
if (_subscribers.ContainsKey(eventName))
{
_subscribers[eventName].Remove(action);
}
}
// 发布事件
// eventName: 事件名称
// data: 事件数据
public void Publish(string eventName, string data)
{
if (_subscribers.ContainsKey(eventName))
{
foreach (var action in _subscribers[eventName])
{
action(data);
}
}
}
}
// 发布者类,负责发布事件
public class Publisher
{
// 依赖的事件聚合器实例
private EventAggregator _eventAggregator;
// 构造函数,初始化事件聚合器
public Publisher(EventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
// 发布事件的方法
// message: 需要发布的事件消息
public void PublishEvent(string message)
{
_eventAggregator.Publish("WeatherUpdate", message);
}
}
// 订阅者类,负责订阅事件
public class Subscriber
{
// 依赖的事件聚合器实例
private EventAggregator _eventAggregator;
// 构造函数,初始化事件聚合器,并订阅"WeatherUpdate"事件
public Subscriber(EventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
_eventAggregator.Subscribe("WeatherUpdate", OnWeatherUpdate);
}
// 处理"WeatherUpdate"事件的方法
private void OnWeatherUpdate(string message)
{
Console.WriteLine($"Subscriber received: {message}");
}
}

实际上使用C#时通常不需要再实现一个 EventAggregator 类,因为C#原生的 event 就已经实现了类似功能。

使用event

这种方式更加贴近C#的事件处理机制,同时也简化了管理订阅者逻辑的需求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 定义一个委托类型,用于表示事件处理方法 
public delegate void WeatherUpdateEventHandler(string message);
// 发布者类,负责发布事件
public class Publisher
{
// 使用event关键字定义一个公开的事件,基于之前定义的委托类型
public event WeatherUpdateEventHandler WeatherUpdated;
// 发布事件的方法
// message: 需要发布的事件消息
public void PublishEvent(string message)
{
// 检查是否有订阅者,如果有则触发事件
WeatherUpdated?.Invoke(message);
}
}
// 订阅者类,负责订阅事件
public class Subscriber
{
// 订阅Publisher的事件
public void Subscribe(Publisher publisher)
{
publisher.WeatherUpdated += OnWeatherUpdate;
}
// 取消订阅Publisher的事件(如果需要)
public void Unsubscribe(Publisher publisher)
{
publisher.WeatherUpdated -= OnWeatherUpdate;
}
// 处理"WeatherUpdate"事件的方法
private void OnWeatherUpdate(string message)
{
Console.WriteLine($"Subscriber received: {message}");
}
}
class Program
{
static void Main(string[] args)
{
// 实例化发布者和订阅者
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
// 订阅事件
subscriber.Subscribe(publisher);
// 发布事件
publisher.PublishEvent("It's raining today!");
// 如果需要,可以在这里调用Unsubscribe方法来取消订阅
// 等待以查看控制台输出
Console.ReadKey();
}
}

在C#中,事件(event)机制本身就是用来实现发布-订阅模式的一个强大工具,它允许对象之间进行松耦合的通信。当一个对象(发布者)的状态改变时,它可以触发一个事件,而其他对这个事件感兴趣的对象(订阅者)可以注册处理程序来响应这个事件。这种模式在很多场景下非常有用,尤其是当需要解耦组件并促进模块化设计时。

尽管如此,在某些复杂的项目或架构中,特别是那些采用如MVVM(Model-View-ViewModel)等设计模式的应用里,可能会发现使用一个 EventAggregator 类更加方便和灵活。EventAggregator 通常作为一个服务存在,允许任何数量的组件发布事件而不必直接引用彼此,同时也能让其他组件订阅这些事件,即使它们之间没有直接的依赖关系。这在大型应用中特别有用,因为它有助于管理大量的事件类型,并且可以更容易地控制事件的生命周期和范围。

类似于在观察者模式中提到过的,同样的,如果想进一步”简化代码”,可以使用 EventHandlerEventArgs 类,这两个类是 C# 中内置的用于事件处理的基类。不过到这一步,观察者模式和发布-订阅模式之间的区别就显得比较模糊了。这两种模式的核心都是关于对象之间的解耦通信,选择哪一种主要取决于设计偏好和项目的具体需求。


发布-订阅模式
https://newztx.github.io/2024/08/11/发布-订阅模式/
作者
Cranky Dove
发布于
2024年8月11日
许可协议