FED

©FrontEndDev.org
2015 - 2024
web@2.23.0 api@2.21.1

javascript 设计模式5——观察者模式

观察者模式在设计模式中被重点提到,因为它应用的场景非常多,而且在模块化设计当中扮演着非常重要的角色。MVC模式中最底层的就是观察者模式,当下流行的javascript框架backbone就是很好地运用该模式的框架之一。观察者模式为我们提供了一些思路,在处理模块或者组件的之间的关系的时候,为了使它们之间的耦合度降低,我们可以采用这种模式思维来编写代码。简单的讲,观察模式的基本原理就是当一个目标需要告诉观察者发生了什么事情的时候,它会向观察者广播一个通知。下面我们来简单的代码阐述一下该模式。

接下来我们开始写js代码:

var guangcha = (function(){//采用模块模式返回值的方法
    var g = {},
        u = 0,//注册方法的索引
        afn = {};
    g.sub = function(n, fn) {//注册事件
        (afn[n] || (afn[n] = [])).push({
            i : (u++).toString(),//可以注册多个同名事件
            func : fn
        });
        return u;//返回U作为该注册函数的唯一标识
    }
    g.pub = function(n, params) {//发布事件
        if(!afn[n]) return false;
        var f = afn[n],
            len = f ? f.length : 0;
        while(len--) {//遍历所有同名注册的事件
            f[len].func(params);
        }
    }
    g.unsub = function(f) {//注销事件
        for(var m in afn) {
            if(!afn[m].length) continue;
            for(var i=0; i<afn[m].length; i++) {
                if(afn[m][i] === f) {
                    afn[m].slice(i, 1);
                    return f;
                }
            }
        }
    }
}
    return g;
})();

在以上代码中我们可以看到,一个观察者的最基础三个方法:注册,发布,注销。在这里,我们引入了索引U,并且用AFN对象作为存储空间来存储它们,这样我们可以注册多个同名的事件而不会覆盖它们,在发布时可以一次性调用。现在我们首先来注册一个事件:

var bonjour = function(p) {
      console.log('BONJOUR MONSIEUR JE ME APPLE '+p); 
}
var hello = function(p) {
    console.log('HELLO SIR MY NAME IS' + p);
}
//开始注册
var sbpn = guangcha.sub('b', bonjour);//b事件附加第一个方法
var sbpn1 = guangcha.sub('b', hello);//b事件附加第二个方法

我们在上面分别注册了两个方法,它们都是附加在b上的,当发布b时,两个方法都会执行。它们分别返回sbpn和sbpn1作为索引,在后面的注销中需要用到该所以.

guangcha.pub('b', 'john');//发布此事件

此时,在浏览器的控制面板中会输出'BONJOUR MONSIEUR JE ME APPLE john'和'HELLO SIR MY NAME IS john'两句话;这样一个完成的订阅/发布流程就走完了。如果需要注销某个订阅的事件,我们可以把索引传入unsub方法内。

guangcha.unsub(sbpn);//注销第一个订阅者

如果此事再次发布b,那么只会有第二句话出现,第一局不会出现了。使用观察订阅者模式可以实现模块之间的解耦。帮助我们处理模块和组件之间的松紧关系。