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

    概念

    发布订阅模式又叫观察者模式,它定义对象间一对多的依赖关系,当一个对象状态发生改变时,所有依赖于它的对象都将得到通知。

    案例

    在js设计模式与开发实践一书中使用的是楼盘信息更新发布的案例。大概内容是:想要买房的人们会订阅自己想要的房产信息,如果房产信息有更新,就会发布给这些人。

    比如佩奇想买一个房子,他可以在售楼处(salesOffices)去订阅这类房产消息,售楼处会将佩奇订阅的信息填写(listen)在客户订阅表中(clientList),当有房子出来时,售楼处就会发送(trigger)信息给佩奇。

    主要内容就是:

    salesOffices={
        clientList:[],
        listen:function,
        trigger:function
    }

    代码如下:

    <!DOCTYPE html>
    <html>
    <head>
        <title>发布订阅</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
    
    </body>
    <script type="text/javascript">
        var consoleText=function (text) {
            // body...
            let body=document.body;
            let div=document.createElement('div');
            div.innerHTML=text;
            body.appendChild(div);
        }
    
        
        //简单发布-订阅模式
        var salesOffices={};
        salesOffices.clientList=[];
    
        salesOffices.listen=function(fn){
            this.clientList.push(fn);
        }
    
        salesOffices.trigger=function(){
            for(var i=0,l=this.clientList.length;i<l;i++){
                this.clientList[i].apply(this,arguments);
            }
        }
    
        salesOffices.listen(function(price,s){
            consoleText('佩奇您好,现在有新楼盘:价格:'+price+",面积:"+s);
        })
    
        salesOffices.listen(function(price,s){
            consoleText('小红您好,现在有新楼盘:价格:'+price+",面积:"+s);
        })
    
        salesOffices.trigger(6000000,120);
    </script>
    </html>

    如果现在佩奇发现房价太高了,自己的预算只能付得起80平房子的首付,售楼处再给佩奇发120平的房子只会扎佩奇的心,所以佩奇只想订阅80平的房子的消息。

    这时候只需要将订阅表分为不同的类型,想要哪种房子的消息就去哪张表填写信息,现在佩奇的信息只能出现在80平的表上了。

    当有80平的信息出来时,只需给将80平订阅表的用户发送消息即可

     

    salesOffices={
        clientList:{
            square80:[],
            square120:[],
        },
        listen:function,
        trigger:function
    }

    代码如下:

    <!DOCTYPE html>
    <html>
    <head>
        <title>发布订阅</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
    
    </body>
    <script type="text/javascript">
        var consoleText=function (text) {
            // body...
            let body=document.body;
            let div=document.createElement('div');
            div.innerHTML=text;
            body.appendChild(div);
        }
    
    
    //可选类型发布-订阅模式
        var salesOffices={};
        salesOffices.clientList={};
    
        salesOffices.listen=function(key,fn){
            //将key类型的订阅存储起来
            if(!this.clientList[key]){
                this.clientList[key]=[]
            }
            this.clientList[key].push(fn);
        }
    
        salesOffices.trigger=function(){
            let key=Array.prototype.shift.call(arguments);
            fns=this.clientList[key];
            if(!fns||fns.length===0){
                return false;
            }
                for(var i=0,l=fns.length;i<l;i++){
                fns[i].apply(this,arguments);
            }
        }
    
        salesOffices.listen("square80",function(price){
            consoleText('小明您好,现在有新楼盘80平:价格:'+price);
        })
    
        salesOffices.listen("square80",function(price){
            consoleText('小李您好,现在有新楼盘80平:价格:'+price);
        })
    
        salesOffices.listen("square110",function(price){
            consoleText('小红您好,现在有新楼盘110平:价格:'+price);
        })
    
        salesOffices.trigger("square80",12000000);
    
    </script>
    </html>

    佩奇之后找到了心仪的房子,已经不需要售楼处再发消息了,所以还有取消订阅的功能。

    而这种发布订阅的模式很有用,很多行业都可以使用它,所以如果能安装即用就会很nice

    代码如下

    <!DOCTYPE html>
    <html>
    <head>
        <title>发布订阅</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
    
    </body>
    <script type="text/javascript">
        var consoleText=function (text) {
            // body...
            let body=document.body;
            let div=document.createElement('div');
            div.innerHTML=text;
            body.appendChild(div);
        }
    
    //通用发布订阅模式
        var event={
            clientList:{},
            listen:function(key,fn){
                if(!this.clientList[key])
                    this.clientList[key]=[];
                this.clientList[key].push(fn);
            },
            trigger:function(){
                var key=Array.prototype.shift.call(arguments);
                var fns=this.clientList[key];
                if(!fns||fns.length===0)
                    return false;
                for(var i=0,l=fns.length;i<l;i++){
                    fns[i].apply(this,arguments);
                }
            },
            remove:function(key,fn){    //取消订阅
                var fns=this.clientList[key];
                if(!fns){// 如果 key 对应的消息没有被人订阅,则直接返回
                    return false;
                }
    
                if(!fn){ // 如果没有传入具体的回调函数,表示需要取消 key 对应消息的所有订阅
                    fns&&(fns.length=0);
                }else{
                    for(var l=fns.length;l>=0;l--){
                        if(fns[l]===fn){
                            fns.splice(l,1);
                        }
                    }
                }
            }
    
        }
    
    
    
        var installEvent=function(obj){
            for(let i in event){
                obj[i]=event[i];
            }
        }
    
        var salesOffices={};
        installEvent(salesOffices);
    
        //key的选择,我觉得应该是某个变化的条件
        salesOffices.listen("square80",f1=function(price){
            consoleText('小明您好,现在有新楼盘80平:价格:'+price);
        })
    
        salesOffices.listen("square80",f2=function(price){
            consoleText('小李您好,现在有新楼盘80平:价格:'+price);
        })
    
        salesOffices.listen("square110",f3=function(price){
            consoleText('小红您好,现在有新楼盘110平:价格:'+price);
        })
    
        salesOffices.remove("square80",f2);
        salesOffices.trigger("square80",80);
    </script>
    </html>
  • 相关阅读:
    C++中重载,重写,隐藏的区别
    以太网(局域网)交换机工作原理
    IP地址、MAC地址、ARP地址解析协议
    Metasploitable渗透测试实战——Windows漏洞 MS08-067复现
    一次对真实网站的SQL注入———SQLmap使用
    多字节与宽字节转换
    char*、string、CString各种字符串之间转换
    国密SM4分组加密算法实现 (C++)
    网络编程——基于UDP的网络化CPU性能检测
    U盘小偷——C++实现U盘插入检测和文件扫描拷贝
  • 原文地址:https://www.cnblogs.com/ellen-mylife/p/13815154.html
Copyright © 2011-2022 走看看