什么是发布订阅模式?
发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。
场景模式
举个例子:如我们平时去餐厅排队吃饭,需要拿了号慢慢排队,这时候假如本宝宝不想直接等而是想边逛街边等待,扫码微信订餐;当排队快到我的时候,就会有微信提醒信息,这时候我只要有提醒信息,就知道何时要吃饭。这里,我,相当于一个订阅者,餐厅则相当于发布者。我扫码订餐,相当于在注册信息。餐厅就有几种功能,一是可以接受用户发过来的信息;二是可以根据访问人数和排序,在微信上通知用户就餐;三是需要一个删除的操作,已经就餐完的用户就没必要继续去推送消息
思路方案
- 创建一个餐厅的对象
- 该对象有个可以装载事件,对事件进行管理的调度中心(微信)
- on 注册事件,相当于该用户进行点餐操作
- emit 根据不同的参数名,通知就餐
- off 已经就餐完毕的用户可以取消监听
实现demo
class Restaurant {
constructor () {
}
/**
* 定义事件来装载事件数据
*/
weixin = {}
/**
* 用户微信扫码
* @param {String} type 事件名,相当于用户
* @param {Function} fn 订阅事件,相当于订餐内容
*/
on (type, fn) {
if (!this.weixin[type]) {
this.weixin[type] = []
}
this.weixin[type].push(fn)
}
/**
* 通知就餐
* @param {String} type 事件名,相当于用户
* @param {...any} message 参数
*/
emit (type, ...message) {
if (!this.weixin[type]) {
return new Error('嘿,我都还没扫码订餐呢!')
}
// 通知用户就餐
for (let i of this.weixin[type]) {
i.call(this, ...message)
}
}
/**
* 删除就餐 (若无第二个参数则删除该事件的订阅和发布)
* @param {String} type 事件名,相当于用户
* @param {Function} fn 事件,相当于订餐内容
*/
off (type, fn) {
if (!type in this.weixin) {
return new Error('咳咳!这人都没扫码点餐呢!')
}
if (!fn) {
delete this.weixin[type]
} else {
const index = this.weixin[type].findIndex(item => item === fn)
if (index === -1) {
console.log('找不到这个点餐呢')
return new Error('找不到这个点餐呢')
}
this.weixin[type].splice(index, 1)
if (this.weixin[type].length === 0) {
delete this.weixin[type]
}
}
}
}
现在,基本的发布订阅模式已经完成拉!现在就让我们来测试一下
let rest = new Restaurant()
const beans = function () {
console.log('来份豆子');
}
const banner = function () {
console.log('来份香蕉派');
}
// 扫码订餐
rest.on('xiaoming', beans)
rest.on('xiaoming', banner)
rest.emit('xiaoming') // 来份豆子 来份香蕉派
rest.off('xiaoming', banner)
rest.off('xiaoming', banner) // 找不到这个点餐呢
rest.emit('xiaoming') // 来份豆子
结语
发布-订阅模式,是为了解决主题对象和订阅者之间功能的耦合,个人理解为的是监控数据和对现有对象的解耦。 例如你订餐的行为实际上就可以理解为一种监控;每人之间的订餐互不影响,这是解耦;
以上写法比较简单,如有不足之处,还望指出,多多学习!