zoukankan      html  css  js  c++  java
  • js发布订阅模式

    订阅-发布模式

     再开始之前先简单介绍下订阅-发布模式,因为这种设计模式在vue代码中起到比较关键的作用。
    首先,简单来说订阅-发布模式是一种定义一对多依赖关系的设计模式,当一个对象状态发生变化时候,所依赖于他的所有对象都将得到通知。
     举个简单例子:很多学生到书店买书,A同学定了一本《js高程》,B同学定了一本《js设计模式》……,但是书店的好多书厂家还没发货,买书者不可能天天跑过去问书到了没,这样书店也应付不过来,买书者也耗费大量时间。所以一般这种情况,书店会留下买书者信息,等书到了通知买书者就ok了。这个例子里,买书者就充当订阅者,书店就是发布者。
    既然是订阅-发布模式,那么它应当具备以下特征:

    • 有许多订阅者,有一个发布者
    • 发布者具有监听订阅者需要订阅什么东西的能力
    • 发布者具有发布信息能力,即自身状态改变通知所有订阅者的能力

    下面根据上面的特点来实现一个最简单的发布订阅模式 :

    // 创建一个发布者
    const publisher = {};
    //发布者储存订阅者信息的对象
    const informations = {}
    //给发布者赋予监听订阅者和它需要信息的能力,sbuscriber_key--订阅者标识,fn--订阅者需要的信息或者服务
    publisher.listen = (sbuscriber_key,fn) => {
        if(!informations[sbuscriber_key] ){       //如果订阅者没有订阅过信息,新建一个数组存储订阅者信息(一个订阅者可能订阅多条信息)
            informations[sbuscriber_key] = [];
        }
        informations[sbuscriber_key].push(fn);    
    }
    //给发布者赋予通知所有订阅者信息的能力
    publisher.inform = (sbuscriber_key,...arg) => {
        if(!informations[sbuscriber_key] || informations[sbuscriber_key].length === 0){
            return new Error('订阅信息不存在')
        }
        informations[sbuscriber_key].forEach(fn => {
            fn.call(this,...arg)
        });
    }
    
    publisher.listen('A',bookName => {
        console.log(bookName+'---到了可以过来取了')
    }) //A订阅一本书
    publisher.listen('B',(bookName,price) => {
        console.log(bookName+'---到了,价格'+price+'是否还要')
    }) //B订阅一本书
    
    //书到了,发布者通知订阅者
    publisher.inform('A','js高程')        //js高程---到了可以过来取了
    publisher.inform('B','js设计模式',50) //js设计模式---到了,价格50是否还要
    

    上面的例子里,比如B同学要到很多书店买书看哪个书店到货了,最后要确切知道去哪个书店买书,造成了B同学和书店的耦合,所以这时候班级统一找一个人C登记每个人要卖的书。买书的不用知道去哪个书店买的,书店也不需要知道卖给谁了,统一由C代理,这样C就是该事件的发布者,根据第一个代码实现,把发布者做一个通用实现:

    function Publisher(){
        this.informations = {}
    }
    Publisher.prototype = {
        constructor : Publisher,
        inform: function (sbuscriber_key,...arg){
            if(!this.informations[sbuscriber_key] || this.informations[sbuscriber_key].length === 0){
                return new Error('订阅信息不存在')
            }
            this.informations[sbuscriber_key].forEach(fn => {
                fn.call(this,...arg)
            })
            console.log(this)
        },
        listen: function (sbuscriber_key,fn){
            if(!this.informations[sbuscriber_key] ){       
                this.informations[sbuscriber_key] = [];
            }
            this.informations[sbuscriber_key].push(fn);    
        },
        remove:function (sbuscriber_key){
            if(!this.informations[sbuscriber_key] ){       
                return;
            }
            this.informations[sbuscriber_key].length = 0;
        }
    }
    
    const p = new Publisher();
    p.listen('A',bookName => {
        console.log(bookName+'---到了可以过来取了')
    }) 
    p.listen('B',(bookName,price) => {
        console.log(bookName+'---到了,价格'+price+'是否还要')
    }) 
    
    p.inform('A','js高程')        
    p.inform('B','js设计模式',50) 
    

    给出通用构造函数Pulisher

  • 相关阅读:
    mtk camera 移植步骤
    Camera 涉及的文件70
    android camera(四):camera 驱动 GT2005
    android camera(二):摄像头工作原理、s5PV310 摄像头接口(CAMIF)
    android camera(三):camera V4L2 FIMC
    android camera(一):camera模组CMM介绍
    【译】第23节---Fluent API
    【译】第22节---Fluent API
    【译】第21节---Fluent API
    【译】第20节---数据注解-InverseProperty
  • 原文地址:https://www.cnblogs.com/yifeng555/p/12341684.html
Copyright © 2011-2022 走看看