观察者模式

  • 定义:又叫发布订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己

观察者模式

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
99
100
101
102
103
104
105
106
107
// 定义发布者基类
interface Subject {
// Attach an observer to the subject.
attach(observer: Observer): void;

// Detach an observer from the subject.
detach(observer: Observer): void;

// Notify all observers about an event.
notify(): void;
}
// 实现发布者
class ConcreteSubject implements Subject {
/**
* @type {number} For the sake of simplicity, the Subject's state, essential
* to all subscribers, is stored in this variable.
*/
public state: number;

/**
* @type {Observer[]} List of subscribers. In real life, the list of
* subscribers can be stored more comprehensively (categorized by event
* type, etc.).
*/
private observers: Observer[] = [];

/**
* The subscription management methods.
*/
public attach(observer: Observer): void {
const isExist = this.observers.includes(observer);
if (isExist) {
return console.log('Subject: Observer has been attached already.');
}

console.log('Subject: Attached an observer.');
this.observers.push(observer);
}

public detach(observer: Observer): void {
const observerIndex = this.observers.indexOf(observer);
if (observerIndex === -1) {
return console.log('Subject: Nonexistent observer.');
}

this.observers.splice(observerIndex, 1);
console.log('Subject: Detached an observer.');
}
public notify(): void {
console.log('Subject: Notifying observers...');
for (const observer of this.observers) {
observer.update(this);
}
}

/**
* Usually, the subscription logic is only a fraction of what a Subject can
* really do. Subjects commonly hold some important business logic, that
* triggers a notification method whenever something important is about to
* happen (or after it).
*/
public someBusinessLogic(): void {
console.log('\nSubject: I\'m doing something important.');
this.state = Math.floor(Math.random() * (10 + 1));

console.log(`Subject: My state has just changed to: ${this.state}`);
this.notify();
}
}
// 订阅者基类
interface Observer {
// Receive update from subject.
update(subject: Subject): void;
}
// 订阅者实现
class ConcreteObserverA implements Observer {
public update(subject: Subject): void {
if (subject instanceof ConcreteSubject && subject.state < 3) {
console.log('ConcreteObserverA: Reacted to the event.');
}
}
}

class ConcreteObserverB implements Observer {
public update(subject: Subject): void {
if (subject instanceof ConcreteSubject && (subject.state === 0 || subject.state >= 2)) {
console.log('ConcreteObserverB: Reacted to the event.');
}
}
}

//使用
// 发布者
const subject = new ConcreteSubject();
// 发布者登记观察者
const observer1 = new ConcreteObserverA();
subject.attach(observer1);

const observer2 = new ConcreteObserverB();
subject.attach(observer2);
// 发布者出发变更,通知观察者
subject.someBusinessLogic();
subject.someBusinessLogic();

subject.detach(observer2);

subject.someBusinessLogic();
  • 缺点:通知顺序无法保证