Open zlx362211854 opened 5 years ago
观察者模式简单来讲就是一对多的依赖关系,当一个对象发生改变,就会通知它的依赖者发生改变。
所以观察者模式必须要具备两个元素,即观察者
和被观察
,观察者订阅被观察者,被观察者通知观察者,如下图:
class Subject {
observers= []
subscribe(func) {
this.observers.push(func)
}
notify(message) {
this.observers.forEach(observer => {
observer(message)
})
}
}
var s = new Subject()
var obverser1 = (message) => {console.log("我是第一个观察者:"+message)}
var obverser2 = (message) => {console.log("我是第二个观察者:"+message)}
s.subscribe(obverser1)
s.subscribe(obverser2)
s.notify("test1")
// => 我是第一个观察者:test1
// => 我是第二个观察者:test1
以上就实现了一个简单的观察者模式。
有时候可能需要多个被观察对象时,为了不创建多个对象,可以引入主题(subject),根据不同的主题通知不同的观察者。
观察者模式可以说是发布-订阅模式,但略有不同,它实现了一对多的依赖关系,当某个对象发生改变时,依赖于它的对象都会得到通知和更新。二者区别在于前者无调度中心,调动方式不同。
document.body.addEventListener("click", function(){
alert("Hello~")
}, false)
document.body.click()
以上订阅了一个在body上的click事件,当点击时触发该事件,向订阅者发布“Hello~”
const event ={
eventList:[],
//监听
listen: (key, fn) =>{
//判断有无该事件
if(!eventList[key]){
eventList[key]=[]
}
//装填函数
eventList[key].push(fn)
},
//触发
trigger:()=>{
//获取事件key
const key = Array.prototype.shift.call(arguments)
const fns = this.eventList[key]
if(!fns || fns.length === 0){ return false}
for(let i=0;i<fns.length;i++){
//执行回调
fns[i].apply(this, arguments)
}
},
//移除
remove:(key, fn)=>{
const fns = eventList[key]
if(!fns.length){ return false)
if(!fn){
//无参数则删除整个回调组
delete eventList[key]
} else {
for(let i=0;i<fns.length;<i++){
if(fn===fns[i]){
//移除指定回调
fns.splice(i,1)
}
}
}
}
const initEvent = (obj) => {
for(let i in event){
obj[i]=event[i]
}
}
const events = {}
initEvent(events)
const fn =(data)=>{console.log(data)}
events.listen('msg', fn)
events.trigger('msg', 'Hello~')
events.remove('msg', fn)
什么时候用js写下数据结构和算法啊
什么时候用js写下数据结构和算法啊
欢迎提供啊,按之前issue的命名格式来就行。
观察者模式有几个要素:
具体实现一个观察者模式如下:
上面代码里使用了es6 的Map对象来存储观察者。注册观察者的时候,每收到一个观察者注册,就按类型将他们分类存放,同一类的观察者存储在一个数组中。触发观察者的代码中,收到触发的命令后,找出触发的类型,调用所有已注册的同类的观察者。删除观察者,就将注册的所有观察者删除,return this方便链式调用
调用示例如下:
至此,就实现了一个简单的观察者模式