最近比较闲,写一写观察者模式。

定义

定义对象间的一种一对多的依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
该模式用于描述对象之间的关系,所以属于行为型模式。

结构

UML图

由上图我们可以看到一共需要构造四个类,两种继承关系,两种关联关系;

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
class Subject {
constructor () {
this.observerList = []
}
attach () {}
detach () {}
notify () {}
}
class Observer {
constructor () {}
update () {}
}
class ConcreteSubject extends Subject {
constructor () {
super();
this.state = null;
}
}
class ConcreteObserver extends Observer {
constructor () {}
update () {}
}

时序图

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
// 目标类
class Subject {
constructor () {
this.observerList = [];
}
// 注册观察者
attach (observer) {
const ob = this.observerList.find(itm => itm === observer);
if (!ob) {
this.observerList.push(observer);
}
return this
}
// 注销观察者
detach (observer) {
const obIndex = this.observerList.findIndex(itm => itm === observer);
return obIndex > -1
? this.observerList.splice(obIndex, 1)[0]
: this;
}
// 触发更新
notify (state) {
if (this.observerList.length) {
this.observerList.forEach(observer => {
observer instanceof Observer && observer.update(state);
})
}
return this;
}
}
// 观察者类
class Observer {
constructor () {}
update () {
console.error('子类请重写 update 方法!');
}
}
class ConcreteSubject extends Subject {
constructor () {
super();
this.value = null;
}
set state (value) {
this.value = value;
this.notify(value);
}
get state (value) {
return this.value;
}
}
class ConcreteObserver extends Observer {
constructor (fn) {
super();
this.updateFn = fn;
}
update (state) {
this.updateFn(state);
}
}
// 测试代码
const ob1Update = price => {
if (price > 1000) {
console.log('价格高于 1000,fuck!');
} else {
console.log('价格小于 1000,God Bless Me!');
}
}
const ob2Update = price => {
if (price > 2000) {
console.log('价格高于 2000,fuck!');
} else {
console.log('价格小于 2000,God Bless Me!');
}
}
let subject = new ConcreteSubject();
let ob1 = new ConcreteObserver(ob1Update);
let ob2 = new ConcreteObserver(ob2Update);
subject.attach(ob1).attach(ob2);
subject.state = 3000;
// -> "价格高于 1000,fuck!"
// -> "价格小于 2000,God Bless Me!"

这样我们就简单实现了一个观察者模式。

实践

对于观察者模式的实践,mobx 就是一个比较典型的案例。
如果觉得源码比较难读,可以参考大搜车团队的s-mobx

图解设计模式