• javascript设计模式学习之八_发布订阅(观察者)模式


    一、发布订阅模式定义

    jQuery中的callbacks,defered,promise本质上就是发布订阅模式的实现。ES6的promise内部实现未开源,不了解具体机制

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

    发布—订阅模式的优点十分明显,一是可以实现时间上的解耦,二是可以实现对象之间的解耦。

    发布—订阅模式的缺点也很明显,订阅者订阅一个消息后,如果该消息最后都没有发生,这个订阅者依旧会存在于内存中。

    javascript中的事件机制就属于发布订阅模式的一种。

    如document.body.addEventListener(),这里document.body就是事件的发布者,addEventListener就是事件发布者提供的一个订阅事件的接口方法,所有其他对象都可以调用这个方法来订阅document.body上发生的对应事件,并自定义自己的事件处理方法。

    一般的发布订阅者模式中,发布者还会提供一个trigger方法,用于发布消息。

    二、java中观察者模式实现

    可以先看看编译型语言如java中观察者模式的实现,参见博客:

    http://www.cnblogs.com/weijunqiang/p/3113828.html

    在java中实现一个自己的发布—订阅模式,通常会把订阅者对象自身当作引用传入发布者对象中,同时订阅者还会提供一个诸如update(本例中是seeMail)的方法,供发布者在合适的时候调用。在Javascript中,可以使用注册回调函数的方式来代替传统的发布—订阅模式,更加简单和优雅。

    三、一个通用的发布-订阅模式 

        var events=(function(){
            var clientList={};
            var listen=function(key,fn){
                if(!clientList[key]){
                    clientList[key]=[];
                }
                clientList[key].push(fn);
            };
            var trigger=function(){
                var key=[].shift.apply(arguments);
                var fns=clientList[key];
                if(!fns||fns.length==0){
                    return false;
                }
                for(var i=0;i<fns.length;i++){
                    fns[i].apply(this,arguments);
                }
            };
            var remove=function(key,fn){
                var fns=clientList[key];
                if(!fns){
                    return false;
                }
                if(!fn){
                    fns.length=0;
                    return;
                }
                for(var i=0;i<fns.length;i++){
                    if(fn===fns[i]){
                        fns.splice(i,1);
                    }
                }
            };
            return{
                listen:listen,
                trigger:trigger,
                remove:remove,
        };
        })();
        
        var installEvent=function(obj){
            for(var i in events){
                obj[i]=events[i];
            }
        };//该函数可以给所有对象添加动态发布功能

    四、发布——订阅模式示例(网站登录

        //现在需要实现网上商城,网站有header头部,nav导航,消息列表,购物车等,
        //这些模块有一个共同的特征,需要ajax获取到用户信息之后才能进行渲染,如header显示用户头像等等
        
        
        //1,实现login对象,作为发布者
        var login={};
        installEvent(login);
        $.ajax('http://www.bobo.com',function(data){
            login.trigger('loginSucc',data);
        });
        
        //各个模块监听登陆成功的消息
        var header=(function(){
            login.listen('loginSucc',function(data){
                header.setAvatar();
            });//监听登陆成功时间
            return {
                setAvatar:function(data){
                        console.log('设置header模块');
                }
            };
        })();
        var nav=(function(){
            login.listen('loginSucc',function(data){
                nav.setAvatar();
            });
            return {
                setAvatar:function(data){
                    console.log('设置nav模块');
                }
            };
        }();
  • 相关阅读:
    从一个word文件中读取所有的表格和标题(1)
    多线程下QAxObject指针为NULL的解决办法
    event对象,ie8及其以下
    日期插件kalendae,遇到的一些问题
    回车键和button按钮都绑定同一个事件,如何避免按回车的时候button重复点击
    jQuery.Cookie.js用法
    jquery操作radio单选按钮、checked复选框。
    拖拽改变div的大小
    [BZOJ 2242] [SDOI 2011] 计算器
    20181016提高测试
  • 原文地址:https://www.cnblogs.com/bobodeboke/p/5647605.html
Copyright © 2020-2023  润新知