98 lines
2.1 KiB
Markdown
98 lines
2.1 KiB
Markdown
---
|
|
nav:
|
|
title: 前端
|
|
path: /fea
|
|
group:
|
|
title: 💊 设计模式
|
|
order: 6
|
|
---
|
|
|
|
## 发布订阅者模式
|
|
|
|
定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使它们能够自动更新自己,当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。
|
|
|
|
### 简单版
|
|
|
|
```js
|
|
// 主题 保存状态,状态变化之后触发所有观察者对象
|
|
class Subject {
|
|
constructor() {
|
|
this.state = 0
|
|
this.observers = []
|
|
}
|
|
getState() {
|
|
return this.state
|
|
}
|
|
setState(state) {
|
|
this.state = state
|
|
this.notifyAllObservers()
|
|
}
|
|
notifyAllObservers() {
|
|
this.observers.forEach(observer => {
|
|
observer.update()
|
|
})
|
|
}
|
|
attach(observer) {
|
|
this.observers.push(observer)
|
|
}
|
|
}
|
|
|
|
// 观察者
|
|
class Observer {
|
|
constructor(name, subject) {
|
|
this.name = name
|
|
this.subject = subject
|
|
this.subject.attach(this)
|
|
}
|
|
update() {
|
|
console.log(`${this.name} update, state: ${this.subject.getState()}`)
|
|
}
|
|
}
|
|
|
|
// 测试
|
|
let s = new Subject()
|
|
let o1 = new Observer('o1', s)
|
|
let o2 = new Observer('02', s)
|
|
|
|
s.setState(12)
|
|
```
|
|
|
|
### 复杂版
|
|
|
|
```js
|
|
/**
|
|
* 发布订阅者模式
|
|
*/
|
|
export default class EventEmitter {
|
|
constructor() {
|
|
this.subs = {}
|
|
}
|
|
|
|
on(event, cb) {
|
|
(this.subs[event] || (this.subs[event] = [])).push(cb)
|
|
}
|
|
|
|
trigger(event, ...args) {
|
|
this.subs[event] &&
|
|
this.subs[event].forEach(cb => {
|
|
cb(...args)
|
|
})
|
|
}
|
|
|
|
once(event, onceCb) {
|
|
const cb = (...args) => {
|
|
onceCb(...args)
|
|
this.off(event, onceCb)
|
|
}
|
|
this.on(event, cb)
|
|
}
|
|
|
|
off(event, offCb) {
|
|
if (this.subs[event]) {
|
|
let index = this.subs[event].findIndex(cb => cb === offCb)
|
|
this.subs[event].splice(index, 1)
|
|
if (!this.subs[event].length) delete this.subs[event]
|
|
}
|
|
}
|
|
}
|
|
``` |