JavaScript设计模式-发布订阅模式

来源:互联网 发布:中宏数据库 编辑:程序博客网 时间:2024/05/29 14:15

何为设计模式?

设计模式其实可以认为是大家约定俗成的一个东西,比如在篮球场上的一些术语,在篮球场上争分夺秒的时候,不可能教练一步一步指导你去怎么做,而是告诉你一个术语,你立马就能反应出来该怎么做。这就是设计模式的现实版例子。在JavaScript开发中,有很多设计模式,经常面试也会被问到一些,比如说发布/订阅者模式,单例模式,迭代器模式等等。今天就先拔一拔发布/订阅模式。

发布/订阅模式与我们JavaScript事件处理很像,因为我们不知道事件什么时候会发生,所以注册一个事件处理程序,等到事件发生了,再去执行之前注册的回调函数。发布/订阅模式与她非常类似。我们先想一下,为什么需要发布/订阅模式?

比如这么一种情况:
我去商场买鞋子,看上了一双特别喜欢的,但是号码没有合适的,然后店员跟我说可以把电话号码留下来,到时候有货了跟我说。另一方面,小明,小红也看上了这双鞋子,也没有合适的号码(同样大小),同样把电话号码留给店员。这样,等鞋子到货之后,店员只需要给当初记下的电话号码发短信,我们三个人就会知道鞋子到货了,决定要不要去买。这就是一个典型的发布/订阅模式。店员就相当于发布者,我们三个就是订阅者,订阅了鞋子到货这一消息。当鞋子到货的时候,发布者就会根据当时留下的手机号码依次发布鞋子到货这一消息。有什么好处呢?
一方面,想买鞋子的人不用常常去那家店或者打电话问,鞋子有没有到货;
另一方面:店员也不关注买鞋子的人是谁,是男是女,只要把消息发布出去就可以了。

发布/订阅模式的应用
最常见的应该就是事件处理函数了。看下面一个例子:

<head>    <script>        window.onload = function(){            function handler(){                alert('点击事件');            }            //订阅者订阅点击事件,订阅时,说明点击之后的回调函数            document.getElementById('ddd').addEventListener( 'click', handler, false);            //发布点击事件            document.getElementById('ddd').click();        }    </script></head><body>    <input id="ddd" type="text" /></body>

自定义事件

除了DOM事件,还可以自定义事件,这个可以通过JavaScript来模拟实现。
首先,我们要确定发布者,然后定义一个缓存列表,订阅者订阅时,将回调函数存入缓存列表中,便于发布时,遍历缓存列表依次触发订阅者回调函数。看一个简单的实现:

var pubObj = {};pubObj.list = [];pubObj.listen = function(fn){    this.list.push(fn);}pubObj.publish = function(){    for(var i = 0; i < this.list.length; i++)    {        this.list[i].apply(this, arguments);    }}//测试pubObj.listen(function( size ) {   //小明订阅消息    console.log('到货鞋子号码为' + size );});pubObj.listen(function( size ){    //我订阅消息    console.log('到货鞋子号码为'+ size);})pubObj.publish(36);pubObj.publish(38);

这里写图片描述
这里写图片描述
可以看到虽然我只订阅36的鞋子到货的消息,但同时也收到了38鞋子到货的消息,这时候怎么去优化呢?我们可以设一个key(或者topic),针对不同的主题有不同的订阅回调,也就是订阅不同,存到不同的缓存列表里面。具体实现如下:

var pubObj = {};pubObj.list = {};pubObj.listen = function(key, fn){    if(!this.list[key])    {        this.list[key] = [];    }    this.list[key].push(fn);}pubObj.publish = function(){    key = Array.prototype.shift.call(arguments);    if(this.list[key] && this.list[key].length > 0)    {        for(var i = 0; i < this.list[key].length; i++)        {            this.list[key][i].apply(this, arguments);        }    }    else    {        return false;    }}//测试pubObj.listen('size38', function( size ) {   //小明订阅消息    console.log('到货鞋子号码为' + size );});pubObj.listen('size36', function( size ){    //我订阅消息    console.log('到货鞋子号码为'+ size);})pubObj.publish(36);pubObj.publish(38);

这里写图片描述

发布/订阅模式暂时先理解到这里,后续还有通用的发布订阅模式,以及一个小例子的应用,后面会再整理。

原创粉丝点击