JavaScript设计模式——观察者模式

观察者模式又被称为发布-订阅模式,是设计模式中的一种行为型模式;

定义:

观察者模式定义了一种一对多的对象依赖关系,当被依赖的对象的状态发生了改变,所有依赖它的对象都会得到通知;

白话解释:

假如你去苹果专卖店买最新款的iphone11,因为iphone11刚出来不久,正处旺季,供货不足;当你去专卖店的时候,店员告诉你暂时没货了,但是你可以留下你的联系方式,如果货到了,会第一时间通知;当然你肯定不会每天都去专卖店问iphone11到货没有,也不会天天给专卖店打电话,因为你有你自己的工作和生活,不可能有那么多闲暇时间;所以此时,店员让你留下联系方式,到货了第一时间通知你,不会给你带来麻烦,而你只需要等着专卖店的电话即可;而这种方法就是一种典型的观察者模式;

首先我们还是来分析一下:

1.订阅方法:我们把联系方式给专卖店店员是属于一种消息订阅的消息,因为只有这样你才能及时的知道iphone11到货了,所有我们需要一个订阅行为的具体方法;

2.预订列表:要知道iphone11是属于新版iphone,所以肯定不会是只有你一个人去预订,所以店员为了方便统计还需要一个预订列表来统计所有的预订者的联系方式以及预订手机版本信息,所以我们这里先给它定义为一个对象;key代表是预订者的联系方式,value代表预订手机版本信息;

3.发布方法:当iphone11到货的时候,专卖店肯定要根据预订列表来进行统一发布消息("iphone11到货了,大家快来抢!!!"),所以专卖店需要一个发布方法来实行具体的发布行为;、

4.取消订阅:万物相对,能订阅肯定就能取消订阅;在等待iphone11到货通知的时候,你急着用手机,所以直接买了华为的某款,所以iphone11暂时对你来说需求不大,因为你已经有了手机所以专卖店的iphone11是否到货对你来说没有任何意义了;所以此时你不想被打扰,需要取消订阅消息;所以我们需要一个取消订阅方法来实现具体的取消订阅的行为;

观察者模式的应用场景:

1、DOM事件

如果你是一个前端开发人员,不管你读这篇文章之前是否已经了解观察者模式,但是我能肯定你已经用过观察者模式;

document.body.addEventListener('click', function() {
    console.log('hello world!');
});

这段代码看着眼熟吗?是的,这是一个DOM事件的监听;我们通过给body订阅click事件(click相当于上面的订阅方法),因为浏览器并不知道你什么时候点击鼠标,所以等你触发click事件的时候才会触发函数给你发布通知(发布方法);DOM事件就是一个观察者模式的实现;

2、vue双向绑定v-model

我们作为前端开发人员,肯定知道vue是一个MVVM模式的框架;vue的核心就是双向绑定,那么双向绑定的实现实际上就是一种观察者模式;因为你首先绑定了一个数据之后(订阅方法),浏览器并不知道你什么时候修改,你页面上所有绑定了该数据或者依赖该数据的节点其实就是一个预订列表,只有等你修改了该数据的值的时候,vue才会通知(发布方法)到依赖该数据的方法/数据进行相应的操作或刷新;

当然观察者模式绝不仅限于这俩种实现场景,在我们的生活中、业务场景中有很多观察者模式的示例,之前我们第一篇工厂模式介绍设计模式的时候就说过了,设计模式是一种解决问题的思路而非一种固定的公式,那么我们怎么实现观察者模式呢?

观察者模式的实现:

    //定义商家
    var merchants = {};
    //定义预订列表
    merchants.orderList = {};
    //将增加的预定者添加到预订列表中   (订阅方法)
    merchants.listen = function(id,info){
        //如果存在
        if(!this.orderList[id]){
            // (预订列表)
            this.orderList[id] = [];
        }
        // 将用户的预定的产品信息存入到数组中
        this.orderList[id].push(info);
    }
    //发布信息(发布方法)
    merchants.publish = function(){
        var id = Array.prototype.shift.call(arguments);
        var infos = this.orderList[id];
        if(!infos || infos.length === 0){
            console.log("您还没有预定信息");
            return false;
        }

        for(var i = 0;i < infos.length;i++){
            console.log("预定成功");
            console.log("尊敬的用户:")
            infos[i].apply(this,arguments);
            console.log("到货了");
        }
    }
    //取消订阅  
    merchants.remove = function(id,fn){
        var infos = this.orderList[id];
        if(!infos){ return false}

        if(!fn){
            console.log(123);
        }else{
            for(var i = 0;i < infos.length;i++){
                if(infos[i] === fn){
                    infos.splice(i,1);
                }
            }
        }
    }
    let customeA = function(){
        console.log("黑色尊享版一台");
    }

    merchants.listen("15172103336",customeA);
    merchants.remove("15172103336",customeA);
    merchants.publish("15172103336");

上面的代码稍微有点长,不过没有很难;首先我们是定义了一个对象是作为商家,然后定义了一个空的对象作为预订列表,再一步步的实现我们的订阅方法和发布以及取消订阅的方法;逻辑不复杂,但是有一些语法需要讲解一下:

发布方法中的var id = Array.prototype.shift.call(arguments);这句的意思是将merchants.publish("15172103336");方法调用的时候第一个参数返回给它然后复制为id,所以其实此时的id值为”15172103336“;

infos[i].apply(this,arguments);这个方法也不是特别好理解,首先infos里装的是预订者的手机号码以及手机版本信息,所以我们infos[i].apply(this,arguments);这个方法其实就是将"15172103336"对应的手机版本信息函数进行调用了一遍;实际上等于infosi;

观察者模式不管是在前端领域还是在现实生活中的应用都是有很常见的场景,学好观察者模式有利用我们学习vue的源码知识,当然不仅限于此,所以观察者模式值得我们好好学习,一句话:"你品,你细品!" 今天付出的努力,在日后总会换成工资来回报你的!哈哈哈

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,639评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,277评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,221评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,474评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,570评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,816评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,957评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,718评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,176评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,511评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,646评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,322评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,934评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,755评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,987评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,358评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,514评论 2 348

推荐阅读更多精彩内容