관찰자 모드
- 게시 및 구독
- 일대 다
예:
- 커피를 주문하고 주문 후 전화를 기다리십시오.
단순화 된 UML 클래스 다이어그램
// 主题 保存状态,状态变化之后触发所有观察者对象
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}`)
}
}
// test
let s = new Subject()
let o1 = new Observer('o1', s)
let o2 = new Observer('o2', s)
let o3 = new Observer('o3', s)
s.setState(1)
s.setState(2)
s.setState(3)
장면 1 jQuery
웹 이벤트 바인딩
<button id="btn1">btn</button>
<script>
$('#btn1').click(funciton () {
console.log(1)
})
$('#btn1').click(funciton () {
console.log(2)
})
$('#btn1').click(funciton () {
console.log(3)
})
</script>
약속
const src = 'https://xxxx.png'
const result = loadImg(src)
result.then(funciton (img) {
console.log('width', img.width)
return img
}).then(function (img) {
console.log('height', img.height)
})
jQuery 콜백
const callbacks = $.Callbacks()
callbacks.add(function(info) {
console.log('fn1', info)
})
callbacks.add(funciton(info) {
console.log('fn2', info)
})
callbacks.add(funciton(info) {
console.log('fn3', info)
})
callbacks.fire('hello')
callbacks.fire('world')
장면 2
nodejs 맞춤 이벤트
const EventEmitter = require('events').EventEmitter
const emitter1 = new EventEmitter()
// 使用1
emitter1.on('some', () => {
console.log('监听some事件1')
})
emitter1.on('some', () => {
console.log('监听some事件2')
})
// 触发some事件
emitter1.emit(some)
// 使用2
emitter1.on('getName', name => {
console.log(name)
})
emitter1.emit('getName', '小白') // emit传递参数过去
// 使用3 继承
// 任何构造函数都可以继承 EventEmitter的方法, on emit
class Dog extends EventEmitter {
constructor(name) {
super()
this.name = name
}
}
const simon = new Dog('simon')
simon.on('bark', function() {
console.log(this.name, ' barked')
}
setInterval(() => {
simon.emit('bark')
}, 500)
// Stream 用到了自定义事件
const fs = require('fs')
// 读取文件的stream 流
const readStream = fs.createReadStream('./data/file1.txt')
const length = 0
// 一点点读数据,监听
readStream.on('data', function() {
length += chunk.toString().length
})
readStream.on('end', function() {
console.log(length)
})
// readline 用到了自定义事件
const readline = require('readline')
const rl = readline.createInterface({
input: fs.createReadStream('./data/file1.txt')
})
const lineNum = 0
rl.on('line', funciton (line) {
lineNum ++
})
rl.on('close', function() {
console.log('lineNum', lineNum)
})
다른 장면
- Nodejs : http 요청 처리, 다중 프로세스 통신,
http 요청
function serverCallback(req, res) {
const method = req.method.toLowerCase() // 获取请求方法
if (method === 'get') {
// 处理get请求代码
}
if (method === 'post') {
// 接收post请求内容
let data = ''
req.on('data', function (chunk) {
// 一点点接收
data += chunk.toString()
})
req.on('end', funciton () {
// 接收完毕,将内容输出
res.writeHead(200, {
'Content-type': 'text/html'})
res.write(data)
res.end()
})
}
}
다중 프로세스 통신
// parent.js
const cp = require('child_process')
const n = cp.for('./sub.js')
n.on('message', (m) => {
console.log(`Parent got message: ${
m}`)
})
n.send({
hello: 'workd'})
// sub.js
process.on('message', m => {
// 监听信息
console.log(`Child got message: ${
m}`)
})
process.send({
foo: 'bar'}) // 发送信息
- Vue 및 React 구성 요소 수명주기 트리거
- vue 시계
설계 원리 검증
- 주체와 관찰자는 분리되어 있으며 능동 트리거링이 아니라 수동 모니터링으로 둘을 분리합니다.
- 개방 및 폐쇄 원칙 준수