发布订阅者模式的理解和应用
2021-07-13 本文已影响0人
JX灬君
详解
ps:什么是设计模式
是设计思路,一定程度提高效率
在基础的23中设计模式中进行使用和优化和改良。
1.发布-订阅者模式定义
- 发布-订阅者模式其实是一种对象间一对多的依赖关系(利用消息队列)
- 当一个对象(state)的状态发生改变时,所有依赖于它的对象都得到状态改变的通知
- 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel)
- 当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时。
- 由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码
2.特征
- 基本事件调用过程
先定义一个普通函数/事件
然后调用 - 发布订阅者模式,则是为了让发布者和订阅者解耦(在发布者和订阅者中间增加一个调度中心)
- 发布订阅者模式是一对多的关系(一个调度中心对应多个订阅者)
- 发布订阅者模式通常会有一个对应消息队列(Array相当于queue)数组的概念[fn1, fn2, fn3]先进先出
- 先定义好消息队列,需要的对象去订阅。当状态改变,对象不再主动触发,而是被动接收。
3.发布订阅者模式的实现思路
- 创建一个类
- 在该类上创建一个缓存列表(调度中心)
- on方法用来把函数fn都加到缓存列表(订阅者注册事件到调度中心)
- emit方法取到event事件类型,根据event值去执行对应缓存列表中的函数(发布者发布事件到调度中心,调度中心处理代码)
- off方法可以根据event事件类型取消订阅
案例讲解
- 去书店买书
- 普通模式:频繁的去调用相应的办法。
去书店,问,没有,回家
过一会再去,问,没有,回家
过一会再去,问,没有,回家
实现思想之一-轮询:setInterval,websocret
影响:网络的负担 - 发布订阅者模式
去书店,问,没有,订阅(on)一个联系方式给店员
有了书,店员就发射(emit)一个电话给用户,触发消息队列(message)去买书。如果我已经买到书,就回复,我已经买到书了 ,不要了off()。
四个部分:message,on,emit,off
emit部分的表现形式:老的框架如jquery-》fire,还有trigger。
实现思想之一-绑定事件:比如给事件绑定点击事件,当点击时,状态发生改变,触发点击事件。(可以理解为发布订阅者模式在前端无处不在)
案例分析
// 1.创建一个分析构造函数类
// 包括4部分(消息队列,$on向消息队列里添加内容,$off删除消息队列里的内容,$emit触发消息队列里面的内容)
// 2.使用构造函数创建一个实例
// 3.使用实例,$on向消息队列里添加内容,$off删除消息队列里的内容,$emit触发消息队列里面的内容
/**
* 分析构造函数
* + 属性: 消息队列
* {
* "click":[fn1, fn2, fn3],
* "abc":[fnA, fnB]
* }
* + 能向消息队列里面添加内容 $on
* + 删除消息队列中的内容 $off
* + 触发消息队列里面的内容 $emit
*/
// 新建类
class Observer {
// 新建构造器
constructor() {
this.message = {}
}
// type 我拜托你要看着的某个行为
// fn 行为发生之后应该做什么事情
$on(type, fn) {
// 先判断有没有这个属性
// 如果没有这个属性,就初始化一个空的数组
// 如果有这个属性,就往他的后面push一个新的fn
// this.message[type] = fn
if(!this.message[type]) {
this.message[type] = []
}
this.message[type].push(fn)
}
$off(type, fn) {
//判断有没有订阅
if(!this.message[type]) return
//判断有没有fn这个参数
//如果没有fn,我就删掉整个事件
if(!fn){
this.message[type] = undefined
return
// 官方方法
//delete this.message[type]
}
//如果有fn我就仅仅只是过滤掉这个方法
this.message[type] = this.message[type].filter((item) => item !== fn)
}
$emit(type) {
//判断是否订阅
if(!this.message[type]) return
this.message[type].forEach(item => {
item()
})
}
}
// 使用构造函数创建一个实例
const person1 = new Observer() // 观察者
// 向person1委托一些内容,帮忙观察
person1.$on("abc", handlerA)
person1.$on("abc", handlerB)
// 整个消息队列全部删掉
// person1.$off("abc")
// 删掉部分消息队列
// person1.$off("abc",handlerA)
person1.$emit("abc")
console.log(person1);
// person1.$on("黑书", handlerA)
// person1.$on("黑书", handlerB)
// person1.$on("白书", handlerB)
// person1.$on("白书", handlerC)
function handlerA() {
console.log("handlerA");
}
function handlerB() {
console.log("handlerB");
}
function handlerC() {
console.log("handlerC");
}
知识点发散
设计模式有哪些
- 结构型模式
- 桥接模式
- 适配器模式
- 装饰器模式
- 代理模式
- 外观(门面)模式
- 组合模式
- 创建型模式
- 建造者模式
- 单例模式
- 抽象工厂模式
- 工厂方法模式
- 静态工厂模式
- 行为型模式
- 模版方法模式
- 策略模式
- 观察者模式
- 责任链模式
- 命令模式
- 访问者模式