zoukankan      html  css  js  c++  java
  • 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模块');
                }
            };
        }();
  • 相关阅读:
    简单明了的带你理解springboot原理和三大核心注解
    Spring Boot(一):入门篇
    【Mysql优化】聚簇索引与非聚簇索引概念
    Mysql索引原理与优化
    Mysql全文索引的使用
    索引的优缺点,如何创建索引
    184 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 04 例:字符串与byte(即:字节)数组间的相互转换
    183 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 03 String常用方法(下)
    182 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 02 String常用方法(上)
    181 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 01 String常用方法简介
  • 原文地址:https://www.cnblogs.com/bobodeboke/p/5647605.html
Copyright © 2011-2022 走看看