JavaScriptデザインパターン-オブザーバーパターン
1.オブザーバーモード
1.1オブザーバーモードの概要
发布 & 订阅
一对多
示例
- コーヒーを注文し、注文後に呼び出されるのを待ちます
1.2オブザーバーパターンクラス図
传统 UML 类图
简化后的 UML 类图
- 左側には
Observer
、观察者
そこにありますupdate() 触发方法
- 右側
Subject
で主题
は、绑定多个观察者
- の件名
observers
A数组 Array
- できた
获取状态 getState()
- できた
设置状态 setState()
- 当
设置状态后
,会触发所有的观察者里的 update 方法
1.3オブザーバーモードのデモンストレーション
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('o2', s)
let o3 = new Observer('o3', s)
s.setState(1)
s.setState(2)
s.setState(3)
1.4オブザーバーモードシーン
1.4.1Webページのイベントバインディング
网页事件绑定
そしてすべてUI
、オブザーバーモードを使用して webview
このレベルのすべて事件监听的机制
- オブザーバーモードを使用しない場合、コード開発はより理解しにくくなります
<button id="btn1">btn</button>
<script>
$('#btn1').click(function () {
console.log(1)
})
$('#btn1').click(function () {
console.log(2)
})
$('#btn').click(function () {
console.log(3)
})
</script>
1.4.2約束
function loadImg(src) {
var promise = new Promise(function (resolve, reject) {
var img = document.createElement('img')
img.onload = function () {
resolve(img)
}
img.onerror = function () {
reject('图片加载失败')
]
img.src = src
})
return promise
}
var src = 'https://www.imooc.com/static/img/index/logo_new.png'
var result = loadImg(src)
result.then(function (img) {
console.log('width', img.width)
return img
}).then(function (img) {
console.log('height', img.height)
})
1.4.3jQuery中コールバック
var callbacks = $.Callbacks()
callbacks.add(function (info) {
console.log('fn1', info)
})
callbacks.add(function (info) {
console.log('fn2', info)
})
callbacks.add(function (info) {
console.log('fn3', info)
})
callbacks.fire('gogogo')
callbacks.fire('fire')
1.4.4Nodejsカスタムイベント
const EventEmitter = require('events').EventEmitter
const emitter1 = new EventEmitter()
emitter1.on('some', () => {
console.log('some event is occured 1')
})
emitter1.on('some', () => {
console.log('some event is occured 2')
})
emitter1.emit('some')
const EventEmitter = require('events').EventEmitter
const emitter = new EventEmitter()
emitter.on('showName', name => {
console.log('event occured', name)
})
emitter.emit('showName', 'zhangsan')
const EventEmitter = require('events').EventEmitter
class Dog extends EventEmitter {
constructor(name) {
super()
this.name = name
}
}
var simon = new Dog('simon')
simon.on('back', function () {
console.log(this.name, 'barked')
})
setInterval(() => {
simon.emit('back')
}, 500)
var fs = require('fs')
var readStream = fs.createReadStream('./data/file1.txt')
var length = 0
readStream.on('data', function (chunk) {
length += chunk.toString().length
})
readStream.on('end', function () {
console.log(length)
})
var readline = require('readline');
var fs = require('fs')
var rl = readline.createInterface){
input: fs.createReadStream('./data/file1.txt')
});
var lineNum = 0
rl.on('line', function(line) {
lineNum++
});
rl.on('close', function() {
console.log('lineNum', lineNum)
});
1.4.5その他のシナリオ
Node.js 中:处理 http 请求;多进程通讯
function serverCallback(req, res) {
var method = req.method.toLowerCase()
if (method === 'get') {
}
if (method === 'post') {
var data = ''
req.on('data', function (chunk) {
data += chunk.toString()
})
req.on('end', function () {
res.writeHead(200, {
'Content-type': 'text/html'})
res.write(data)
res.end()
})
}
}
var cp = require('child_process')
var n = cp.fork('./sub.js')
n.on('message', function (m) {
console.log('PARENT got message: ' + m)
})
n.send({
hello: 'world'})
process.on('message', function (m) {
console.log('CHILD got message: ' + m)
})
process.send({
foo: 'bar' })
class Login extends React.Component {
constructor(props, context) {
super(props, context);
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
this.state = {
checking: true
}
}
render() {
return (
<div>
<Header title="登录" history={
this.props.history}/>
</div>
)
}
componentDidMount() {
this.doCheck()
}
}
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
1.5オブザーバーパターンの設計原理の検証
主题和观察者分离,不是主动触发而是被动监听,两者解耦
符合开放封闭原则