发布订阅模式

        观察者模式中,目标者更新则观察者就要接收消息,有可能部分观察者不需要这条消息,或者目标者只需要发送消息给部分观察者,这种情况观察者模式不是很使用,需要用到发布订阅模式。

        发布订阅模式的发布者和订阅者松散耦合,二者之外添加了事件中心,发布者只管发布信息到总线,不管订阅者是否需要;订阅者也只管在总线获取自己需要的信息,并且可以取消自己不再需要的信息。

设计思路:

1)创建一个缓存列表对象

2)用on方法将回调函数fn都放入缓存列表

3)emit方法取argument里的第一个当作key,根据key值执行

4)remove中根据key值取消订阅

实例

let books = {
    list: {},
    // key是订阅的类别
    on(key,fn) { // 订阅列表
        if(!this.list[key]) {
            this.list[key] = []
        }
        this.list[key].push(fn)
    },
    // key表示哪个类型需要发布
    emit(key) { // 发布
        let fns = this.list[key]
        if(!fns || fns.length == 0){
            return false
        }
        fns.forEach(fn => {
            fn.apply(this)
        })
    },
    remove(key,fn) { // 从订阅列表移除
        let fns = this.list[key]
        if(!fns || fns.length == 0){
            return false
        }
        if(!fn) {
            fns && (fns.length = 0)
        }else {
            fns.forEach((index,i) => {
                if(index == fn){
                    fns.splice(i,1)
                }
            })
        }
    }
}

function zs() {
    console.log('张三收到更新')
}
function ls() {
    console.log('李四到更新')
}
function ww() {
    console.log('王五收到更新')
}

// 三个方法订阅了青年大学习
books.on('青年大学习',zs)
books.on('青年大学习',ls)
books.on('青年大学习',ww)
// 张三订阅了时代周刊
books.on('时代周刊',zs)

// 青年大学习发布更新
console.log('青年大学习更新')
books.emit('青年大学习')
// 打印结果: 
// 青年大学习更新
// 张三收到更新
// 李四收到更新
// 王五收到更新

console.log('')
console.log('时代周刊更新')
books.emit('时代周刊')
// 打印结果: 
// 时代周刊更新
// 张三收到更新

        观察者模式中,只需要把观察者放入一个对应的列表中,更新时候所有的观察者都会收到更新;

        发布订阅模式中,总线中有多个列表,每个不同的列表包含不同的订阅者,每个列表更新,也只会通知到对应的订阅者。

简单封装

let event = {
    list: {},
    on(key,fn) { // 订阅列表
        if(!this.list[key]) {
            this.list[key] = []
        }
        this.list[key].push(fn)
    },
    emit(key) { // 发布
        let fns = this.list[key]
        if(!fns || fns.length == 0){
            return false
        }
        fns.forEach(fn => {
            fn.apply(this)
        })
    },
    remove(key,fn) { // 从订阅列表移除
        let fns = this.list[key]
        if(!fns || fns.length == 0){
            return false
        }
        if(!fn) {
            fns && (fns.length = 0)
        }else {
            fns.forEach((index,i) => {
                if(index == fn){
                    fns.splice(i,1)
                }
            })
        }
    }
}

        event.on 和 event.remove方法需要传入类型和方法,将指定的方法传入或移出该类型;event.emit 只需要传入类型,该类型的所有订阅者都会收到通知。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尘世迷途小书童p

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值