设计模式 <行为型> | 观察者模式

观察者模式(Observer Design Pattern)

在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知,被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)。 消息队列 事件总线 就是观察者模式。

结构图:

角色:

  1. 抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一组接口,可以增加和删除观察者对象。
  2. 具体主题(ConcreteSubject):将有关状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知
  3. 抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
  4. 具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

适用场景:

  1. 需要通过事件触发场景。

优点:

  1. 可以很轻松的添加观察者/订阅者,符合开闭原则。

缺点:

  1. 如果观察者/订阅者过多通知将会很耗时。
  2. 无法保证通知的顺序。

代码(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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

/// <summary>
/// 被观察者
/// </summary>
public class MyBlog : Blog
{
public MyBlog(string title, string content)
: base(title, content)
{
}
}

/// <summary>
/// 抽象观察者/订阅者 (Observer)
/// </summary>
public interface IObserver
{
void Update(Blog tenxun);
}

/// <summary>
/// 具体观察者/订阅者
/// </summary>
public class ConcreteObserver : IObserver
{
public string Name { get; set; }

public ConcreteObserver(string name)
{
Name = name;
}

public void Update(Blog blog)
{
Console.WriteLine($"订阅者 {Name} 观察到了{blog.title}{blog.content}");
}
}


/// <summary>
/// (Subject)抽象主题
/// </summary>
public abstract class Blog
{
// 保存订阅者列表
private List<IObserver> observers = new List<IObserver>();

public string title { get; set; }
public string content { get; set; }

public Blog(string title, string content)
{
this.title = title;
this.content = content;
}

/// <summary>
/// 添加订阅者
/// </summary>
/// <param name="ob"></param>
public void AddObserver(IObserver ob)
{
observers.Add(ob);
}

/// <summary>
/// 删除订阅者
/// </summary>
/// <param name="ob"></param>
public void RemoveObserver(IObserver ob)
{
observers.Remove(ob);
}

/// <summary>
/// 通知观察者
/// </summary>
public void NotifyObservers()
{
// 遍历订阅者列表进行通知
foreach (var ob in observers)
{
ob.Update(this);
}
}
}


Blog blog = new MyBlog("标题", "内容");

// 添加订阅者
blog.AddObserver(new ConcreteObserver("1"));
blog.AddObserver(new ConcreteObserver("2"));
blog.AddObserver(new ConcreteObserver("3"));
blog.AddObserver(new ConcreteObserver("4"));

// 告知订阅者
blog.NotifyObservers();

最后

上面的代码算是观察者模式的模板代码,只能反映大体的设计思路。在真实的软件开发中,并不需要照搬上面的模板代码。观察者模式的实现方法各式各样,函数、类的命名等会根据业务场景的不同有很大的差别,万变不离其宗,设计思路都是差不多的

观察者模式的应用场景非常广泛,小到代码层面的解耦,大到架构层面的系统解耦,再或者一些产品的设计思路,都有这种模式的影子。比如,邮件订阅、RSS Feeds,本质上都是观察者模式。不同的应用场景和需求下,这个模式也有截然不同的实现方式,有同步阻塞的实现方式,也有异步非阻塞的实现方式,有进程内的实现方式,也有跨进程的实现方式。


设计模式 <行为型> | 观察者模式
http://example.com/posts/64667.html
作者
她微笑的脸y
发布于
2023年3月7日
许可协议