资讯专栏INFORMATION COLUMN

JS每日一题:设计模式-如何理解观察者(发布订阅)模式?

baishancloud / 1713人阅读

摘要:期设计模式如何理解观察者发布订阅模式定义观察者模式又叫发布订阅模式,它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己生活实例理解你今天去看一个

20190411期

设计模式-如何理解观察者(发布订阅)模式?

定义: 观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己

生活实例理解:你今天去看一个楼盘,去了之后发布楼盘还没有对外销售,你不知道楼盘时候会对外销售,于是你找了楼盘的负责人,告诉他什么时候楼盘开始销售了电话通知你,然后想要买的人不是你一个,其它人也是通过留电话的方式给销售负责人来及时获取消息

不难发现,上面的例子正好对应上我们的观察者模式的定义, 多个想要买房的人同时订阅了一个主题(楼盘对外销售),这个主题更新时,这些观察者(买房)都会作出相应的动作

最熟悉的代码理解:

实际上,我们经常用到的事件绑定就是发布订阅模式

在这里我们想在用户点击的时候做出相应的处理,但是我们不知道用户在什么时候去点击,所以我们去订阅body上的click事件,在这里我们还可以去随意增加订阅者,这样并不影响我们的发布者

document.body.addEventListener("click",function(){
  console.log("JS 每日一题")
},false)

document.body.addEventListener("click",function(){
  console.log("今天你打卡了吗?")
},false)
实现一个简版的观察者

首先我们顺一下思路

谁是发布者

谁是订阅者

发生改变时怎么通知订阅者作出相应动作

const Boss = {} //楼盘销售负责人
Boss.clientList = []; // 存放订阅者的回调
Boss.listen = function(fn){ // 增加订阅者
    this.clientList.push(fn); // 将买房人的号码缓存起来
}
Boss.trigger = function(){ // 发布消息
    for(var i=0,fn; fn= this.clientList[i++];){
      fn.apply(this,arguments)
    }
}

Boss.listen(function(msg){
  console.log(msg) // 开始销售了
})

cdBoss.trigger("开始销售了") // 发布消息

我们已经实现在最简易版的发布订阅,但其实是存在问题的,每个人可能订阅户型是不同的, 上面我们实现的是,只要一开始销售就通知所有订阅的人,显然是不合理的,我们将代码再来改写一下

// 订阅时给其加一个key做为标识,就相当于key就是订阅者的身份
Boss.listen = function(key, fn){
    if (!this.clientList[key]) {
      // 如果没有此类订阅,就给该类订阅增加一个缓存列表 
      this.clientList[key] = []
    }
    this.clientList[key].push(fn); 
}

Boss.trigger = function(){ // 发布消息
    const key = Array.prototype.shift.call(arguments),
    // 取出消息类型
    fns = this.clientList[key] 
    if (!fns || !fns.length) return // 如果该类消息没有订阅直接返回
    for (var i = 0, fn; fn = fns[i++]) {
        fn.apply(this, arguments)
    }
}

Boss.listen("老王", function (msg) {
  console.log("老王订阅户型" + cdName)
}) 
Boss.listen("老李", function (cdName) {
  console.log("老李订阅户型" + cdName)
}) 
Boss.trigger("老王", "143平米");
Boss.trigger("老李", "888平米");

好了,经过改写,消息只会推送给相关的订阅者了

总结

时间上的解藕

对象之间的解藕

总的来说,观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化

关于JS每日一题

JS每日一题可以看成是一个语音答题社区
每天利用碎片时间采用60秒内的语音形式来完成当天的考题
群主在次日0点推送当天的参考答案

注 绝不仅限于完成当天任务,更多是查漏补缺,学习群内其它同学优秀的答题思路

点击加入答题

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103455.html

相关文章

  • JS设计模式入门和框架中的实践

    摘要:下面笔者就结合诸如的的里面的里面的来给大家简单介绍下设计模式在这些库语法和框架中的使用。笔者认为把设计模式单独抽象出来探讨,就和算法中抽象出来冒泡排序一样,是为了描述一种常用的。 本文为饥人谷讲师slashhuang原创文章。 在编写JS代码的过程中,运用一定的设计模式可以让我们的代码更加优雅、灵活。 下面笔者就结合诸如redux的subscribe、ES6的class、vue里面的$...

    lmxdawn 评论0 收藏0
  • JS设计模式入门和框架中的实践

    摘要:下面笔者就结合诸如的的里面的里面的来给大家简单介绍下设计模式在这些库语法和框架中的使用。笔者认为把设计模式单独抽象出来探讨,就和算法中抽象出来冒泡排序一样,是为了描述一种常用的。 本文为饥人谷讲师slashhuang原创文章 在编写JS代码的过程中,运用一定的设计模式可以让我们的代码更加优雅、灵活。 下面笔者就结合诸如redux的subscribe、ES6的class、vue里面的$d...

    ccj659 评论0 收藏0
  • JS每日一题:函数式编程中代码组合(compose)如何理解?

    摘要:期函数式编程中代码组合如何理解定义顾名思义,在函数式编程中,就是将几个有特点的函数拼凑在一起,让它们结合,产生一个崭新的函数代码理解一个将小写转大写的函数一个在字符后加的函数将两个函数组合起来这里假设我们实现了每日一题每日一题显示结果里上面 20190315期 函数式编程中代码组合(compose)如何理解? 定义: 顾名思义,在函数式编程中,Compose就是将几个有特点的函数拼凑在...

    Kaede 评论0 收藏0
  • JS每日一题: 小程序页面之间如何通信?

    摘要:小程序页面之间如何通信首先将通信的模型列举出来分为以下几种兄弟页面间通信父路径页面向子路径页面通信子路径页面向父路径页面通信通信的方式本地存储全局对象发布订阅缓存整个至利用激活方法,通过传递数据清空上次通信数据同一样,利用激活方法,通过读写 20190227 小程序页面之间如何通信? 首先将通信的模型列举出来, 分为以下几种 兄弟页面间通信 父路径页面向子路径页面通信 子路径页面向父...

    RancherLabs 评论0 收藏0
  • JS每日一题:设计模式-如何理解工厂模式?

    摘要:期设计模式如何理解工厂模式定义创建对象的接口,让子类决定实例化哪个类。适用场景需要根据不同参数产生不同实例,这些实例都有相同的行为这时候我们可以使用工厂模式,简化实现的过程,同时也可以减少每种对象所需的代码量。 20190408期 设计模式-如何理解工厂模式? 定义: 创建对象的接口,让子类决定实例化哪个类。工厂方法将类的实例化延迟到子类,而子类可以重写接口方法以便创建的时候指定自己的...

    kevin 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<