JS设计模式-观察者模式
Posted 总在落幕后
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS设计模式-观察者模式相关的知识,希望对你有一定的参考价值。
前言
设计模式,是一套被反复使用、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。今天小编带大家了解一下js设计模式中的观察者模式
正文
简述
观察者模式,是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。事实上,观察者模式处处体现在我们平时的code。如
window.addEventListener('click', function(){})
在DOM节点上绑定过事件函数便是观察者模式的一种应用。
实现
下面简单介绍常见的用法。
一、手动触发型
下面是一个简单EventListener的实现:
function checkListener(listener) {
if (typeof listener !== 'function') {
throw new Error('listener must be a Function');
}
}
class EventListener {
constructor() {
this.events = Object.create(null)
}
addEventListener(type, listener) {
checkListener(listener)
this.events[type] ? this.events[type].push(listener) : (this.events[type] = [listener])
}
removeEventListener(type, listener) {
checkListener(listener)
if (!this.events) return this
let list = this.events[type]
if (!list) return this
if (list === listener || listener === undefined) list = undefined
let idx = list.findIndex(fun => fun === listener)
if (idx !== -1) list.splice(idx, 1)
return this
}
emit(type, ...args) {
const _events = this.events
if (!_events || !_events[type]) return false
const handler = _events[type]
if (handler === undefined) return false
for (let i = 0; i < handler.length; ++i) {
handler[i].apply(this, args)
}
}
}
类EventListener使用ES6的class声明,其构造函数会创建一个event的空对象,用于存储事件类型(key)和相对应的事件函数(value)。
addEventListener和removeEventListener函数都有两个参数type, listener,用于添加和删除相对应type的响应函数listener。
emit就是我们触发某事件的函数,通过传入事件的类型,会循环调用listener函数即观察者们,并通过apply传递参数。
现在,我们执行下以下代码:
const event = new EventListener()
const h1 = function () {
console.log('h1 : 我被触发了')
}
const h2 = function (arg1, arg2) { // 带有参数
console.log(`h2 : 我被触发了, arg1 = ${arg1}, arg2 = ${arg2}`)
}
const h3 = function () {
console.log('h3 : 我被触发了')
}
event.addEventListener('zty', h1)
event.addEventListener('zty', h2)
event.addEventListener('zty', h3)
event.emit('zty', 123, 456) // 触发函数时传递函数
console.log('------------------')
event.removeEventListener('zty', h3) // 删除h3观察者
event.emit('zty')
console.log('------------------')
console.log('event = ', event)
在浏览器中我们可以看结果。如想象的一样,emit触发了存储events中的函数
上面我们介绍了手动触发型,下面我们讲讲自动触发的
二、自动触发型
话不多说上代码:
// 接收状态变化,触发每个观察者
class Subject {
constructor() {
this.state = 0
this.observers = []
}
setState(state) {
this.state = state
this.notify()
}
getState() {
return this.state
}
attach(observer) {
this.observers.push(observer)
}
notify() {
this.observers.forEach(observer => {
observer.update()
})
}
}
// 观察者,等待被触发
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()}`)
}
}
类Subject中的observers存储订阅state变化的观察者数组。 进行setState操作时会触发notify函数,遍历数组中的观察者并调用他们的update方法。
让我们看看代码的执行结果
输入代码
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)
console.log('------------------')
console.log('s = ', s)
输出
结果也如想象的一样,setState的时候触发了观察者的update方法。
结束语
观察者主要实现就是通过数组存放观察者,然后通过函数循环遍历数组调用观察者的函数。平常中我们可以看到很多使用观察者模式的例子,如node核心模块event中的EventEmitter,也就是上诉例子一;Vue中的watch和例子二主要思想差不多。
最后,希望文章中的内容可以对大家有所帮助,欢迎讨论,感谢支持~
以上是关于JS设计模式-观察者模式的主要内容,如果未能解决你的问题,请参考以下文章