介绍
- 发布订阅
- 一对多(1对n)
示例
- 订报纸
- 订牛奶
UML类图
代码
// 保存所有状态,状态变化后触发所有观察者对象
class Subject {
constructor() {
this.state = 0
this.observers = []
}
getState() {
return this.state
}
setState(state) {
this.state = state
this.notifyAllObservers()
}
attach(observer) {
this.observers.push(observer)
}
notifyAllObservers() {
this.observers.forEach(observer => {
observer.update()
})
}
}
// 观察者
class Observer {
constructor(name, subject) {
this.name = name
this.subject = subject
this.subject.attach(this)
}
update() {
console.log(`name:${this.name} update, state: ${this.subject.getState()}`);
}
}
// test
const s = new Subject()
const o1 = new Observer('o1', s)
const o2 = new Observer('o2', s)
const o3 = new Observer('o3', s)
s.setState(1)
场景
- 网页事件绑定 ```html
- Promise
- jquery callbacks
- nodejs 自定义事件
- EventEmitter
```javascript
const EventEmitter = require('events').EventEmitter
const events = new EventEmitter()
// 监听 some 事件
events.on('some', info => {
console.log('fn1', info)
})
// 监听 some 事件
events.on('some', info => {
console.log('fn2', info)
})
// 触发 some 事件
events.emit('some', 'xxxxxx')
const EventEmitter = require('events').EventEmitter
class Dog extends EventEmitter {
constructor(name) {
super()
this.name = name
}
}
let dog = new Dog('dog1')
dog.on('bark', (name) => {
console.log(name, 'bark-1')
})
dog.on('bark', (name) => {
console.log(name, 'bark-2')
})
setInterval(() => {
dog.emit('bark', 'ss')
}, 1000)
- Stream ```javascript const fs = require(‘fs’) const path = require(‘path’)
const stream = fs.createReadStream(path.resolve(__dirname, ‘../release/bundle.js’))
let length = 0 stream.on(‘data’, (chunk) => { let len = chunk.toString().length console.log(‘len’, len); length += len }) stream.on(‘end’, () => { console.log(‘length’, length); })
- readline
```javascript
const readline = require('readline')
const fs = require('fs')
const path = require('path')
const rl = readline.createInterface({
input: fs.createReadStream(path.resolve(__dirname, '../package-lock.json'))
})
let lineNum = 0
rl.on('line', (line) => {
lineNum++
})
rl.on('close', () => {
console.log('lineNum', lineNum)
})
- nodejs中处理http请求(post),多进程通信(child_process)
- vue,react组件生命触发
- vue的watch
设计原则验证
- 主题和观察者分离,不是主动触发,而是被动监听,两者解耦
- 符合OCP