# 观察者模式
观察者模式属于行为型模式,将不同行为代码解耦
观测者模式(Observer Design Pattern)也被称为发布订阅模式(Publish-Subscribe Design Pattern)。
在GoF的《设计模式》中,它的定义如下
在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知
一般情况下,被依赖的对象叫作被观察者(Observable),依赖的对象叫做观察者(Observer).
也会有其他叫法,Subject-Observer, Publisher-Subscriber, Producer-Consumer, EventEmitter-EventListener,Dispatcher-Listener。
在这种模式中,一个目标对象(被观察者Observable)管理所有的依赖于它的对象(观察者Observer),并且在它本身的状态发生变化的时候主动发出通知。这通常通过调用观察者提供的某个函数来实现。
class Subject{
constructor() {
this.observers = []
}
registerObserver(observer) {
this.observers.push(observer)
}
notifyObservers(msg) {
this.observers.forEach(observer => {
observer.update(msg)
})
}
}
class Observer {
update(msg) {
console.log(this.name + '更新了:' + msg )
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
场景设计题需求如下:
用户注册,注册后需要给用户发送奖励金,给用户下发系统消息
class UserController {
constructor() {
this.observers = []
}
register() {
// const { ctx } = this
// const { phone, name } = ctx.request.body;
// const userid = ctx.modle.create({phone, name })
console.log('注册成功')
this.notifyObservers('12345');
}
registerObserver(observer) {
this.observers.push(observer)
}
notifyObservers(userId) {
this.observers.forEach(observer => {
observer.handlerRegister(userId)
})
}
}
// 系统消息
class SystemInfo {
sendMsg(userid) {
console.log(`系统消息已发送`)
// 存信息到数据库
// 下发通知
}
handlerRegister(userid) {
this.sendMsg(userid)
}
}
// 发送奖励金
class Payment{
awardPayment(userid) {
// 下发奖励金
console.log(`奖励金已下发`)
}
handlerRegister(userid) {
this.awardPayment(userid)
}
}
const userController = new UserController()
userController.registerObserver(new SystemInfo() ) // 发送系统消息
userController.registerObserver(new Payment() ) // 下发通知
userController.register()
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
需求变更,用户注册成功后需要给用户推送他可能认识人。我们只需要增加一个观察者及可以了
class UserController {
constructor() {
this.observers = []
}
register() {
// const { ctx } = this
// const { phone, name } = ctx.request.body;
// const userid = ctx.modle.create({phone, name })
console.log('注册成功')
this.notifyObservers('12345');
}
registerObserver(observer) {
this.observers.push(observer)
}
notifyObservers(userId) {
this.observers.forEach(observer => {
observer.handlerRegister(userId)
// 异步优化
// setTimeout(() => {
// observer.handlerRegister(userId)
// })
})
}
}
// 系统消息
class SystemInfo {
sendMsg(userid) {
console.log(`系统消息已发送`)
// 存信息到数据库
// 下发通知
}
handlerRegister(userid) {
this.sendMsg(userid)
}
}
// 发送奖励金
class Payment{
awardPayment(userid) {
// 下发奖励金
console.log(`奖励金已下发`)
}
handlerRegister(userid) {
this.awardPayment(userid)
}
}
// 推荐系统
class RecommenderSystem {
getRecommendedList(userid) {
// 推荐可能认识的人
console.log(`认识的人已推荐`)
}
handlerRegister(userid) {
this.getRecommendedList(userid)
}
}
const userController = new UserController()
userController.registerObserver(new SystemInfo() ) // 发送系统消息
userController.registerObserver(new Payment() ) // 下发通知
userController.registerObserver(new RecommenderSystem() ) // 推荐可能认识的人
userController.register()
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
# 好文推荐
- https://medium.com/@huytrongnguyen1985/from-pub-sub-pattern-to-observer-pattern-f4ae1e425cc9
在上述的方案中,观察者需要注册到被观察者中,被观察者需要依次遍历观测者来发消息, 我们还可以基于消息队列的实现方式来实现这个功能,被观测者和观察者解耦会更彻底。
被观察者完全不感知观察者,观察者也完全不感知被观察者。被观察者只管发送消息到消息队列 观测者只管从消息队列中读取消息执行响应的逻辑。
数据是被观察者 也就是 Subject,使用数据的是观察者
而dep的写法其实是发布订阅模式的写法,但是因为有defineProperty,导致只要值改变就会触发notify。
dep是发布-订阅模式的中间管理者,通过他的notify去发布 通过addsup去添加订阅者列表 setter相当于发布者 watcher相当于订阅者
依赖收集本身就是发布过程……
说起Vue的响应式就不得不说他的设计模式,
他采用了 行为型的 观察者模式
接下来我们先用ts实现一个观察者模式 观察者模式也叫做发布订阅模式