js的设计模式之观察者模式
三大问题
- 什么是观察者模式
- 有什么需要注意的地方
- 有什么优缺点
什么是观察者模式
观察模式的实质:就是你可以对程序中的某个对象的状态进行观察,并且在其发生改变(触发)时能够将消息告知每一个观察者
关系
被观察者触发---->通知每个观察者
或者
发布者触发---->通知每个订阅者
观察者模式中存在两种角色:被观察者和观察者,也就是发布者(被观察者)和订阅者(观察者)
。
作用
当到达某个状态或者动作,执行发布者,然后通知到订阅者,要不要在这个状态,做点什么
说明
观察者模式中,(常见场景)并不是一个对象调用另一个对象的方法,而是一个对象订阅另一个对象的特定活动并在状态改变后活得通知。当发生了一个重要事件时,发布者将会通知所有的订阅者并且可能经常以事件对象的形式传递消息
简单实现
let event = {
//用来放订阅者
list:[],
//添加订阅者
addListen(fn){
this.list.push(fn)
},
//发布消息
trigger(){
for(let i = 0,fn; fn = this.list[i++];){
fn.apply(this,arguments)
}
}
}
event.addListen(()=>{
conosle.log("event: click")
})
event.addListen(()=>{
conosle.log("event: hover")
})
event.trigger()
简单实现了一个不明确动作的发布订阅
完善版的发布订阅
Object.prototype.$subscription = function (key, cb) {
this.$subscriptionObj = this.$subscriptionObj || {};
this.$subscriptionObj[key] = this.$subscriptionObj[key] || [];
this.$subscriptionObj[key].push(cb);
}
Object.prototype.$dispatch = function (key, ...arg) {
if (!Object.keys(this.$subscriptionObj).length) return;
for (let i = 0; i < this.$subscriptionObj[key].length; i++) {
this.$subscriptionObj[key][i].apply(this, arg)
}
}
let test = {};
test.$subscription('click', (a) => {
console.log(a, '执行了第一次')
});
test.$subscription('click', (a) => {
console.log(a, '执行了第二次')
});
test.$subscription('event', (a) => {
console.log(a, '光添加订阅,并没有发布,不会执行')
})
btn.onclick = () => {
test.$dispatch('click', { a: 1 })
}
总结
- 只要某个对象派发了事件,只要获取到这个对象的引用,就可以通过添加订阅者的方式,对派发的事件做进一步拦截处理
- 优点:适合模块之间使用,耦合性比较低
- 缺点:对于初学者来说可能可读性不是很高