JS中观察者模式的简单实现

一、定义

观察者模式是软件设计模式的一种常见的设计模式,又称发布订阅模式。在这种模式中,并不是单纯的一个对象调用另一个对象的方法,而是一个对象订阅另一个对象的特定活动并在其状态发生改变后获得通知,然后执行相应的操作。订阅者也称为观察者,而被观察的对象则被称为发布者或主题。当一个事件发生,发布者将会向所有订阅此事件的对象以事件对象的形式传递消息。

比如说:前段时间世界杯,很多人都看球赛,但人精力还是有限的,经常可能会因为这样或哪样的原因错过看球赛的时间,在这种情况下很多直播网站提供了一个很贴心的服务,那就是开播提醒,当用户订阅了这个提醒,那么在某个时刻比如球赛开播前5分钟系统会给所有订阅开播提醒的用户以短信或者其他有效形式发送通知,提醒用户球赛马上开播了,这个就是观察者模式的典型应用。

二、要素

观察者模式最重要的两个要素是:发布者、订阅者(观察者),发布者发送消息,订阅者订阅/删除特定消息并接受发布者发送的消息。

三、实现

1、思路

首先,为了记录所有的订阅者我们需要有一个地方存储他,我们姑且叫其listeners,其数据类型为数组,接着我们需要实现几个方法:

(1)订阅方法,对于触发一次就失效的方法我们将其命名为once,对于始终触发的我们叫其on,订阅方法主要就是向listeners中添加监听器,其实一个对象,包含一个事件类型type和一个触发函数fn,而once和on的区别就是是否在触发一次后就从listeners中移除该监听器。

(2)取消订阅方法,remove,主要负责从listeners中移除特定类型的监听器

(3)发布方法,emit,主要负责根据事件类型从isteners中取出所有该事件类型的监听器并触发。

当然如果细究,还应该提供移除所有监听器的方法,这里就不再赘述了。

2、代码实现:

var Event = function() {
    this._listeners = [];
}
Event.prototype = {
    on: function(type, fn) {
        if (typeof this._listeners[type] === "undefined") {
            this._listeners[type] = [];
        }
        if (typeof fn === "function") {
            this._listeners[type].push(fn);
        }
    },
    remove: function(type, fn) {
        var eventArr = this._listeners[type];
        if (typeof type === "string" & amp; & amp; eventArr instanceof Array) {
            if (typeof fn === "function") {
                for (var i = 0; i & lt; eventArr.length; i++) {
                    if (fn.toString() === eventArr[i].toString()) {
                        this._listeners[type].splice(i, 1);
                        break;
                    }
                }
            } else {
                this._listeners[type].length = 0;
            }
        }
    },
    emit: function(type, data) {
        var eventArr = this._listeners[type];
        if (eventArr instanceof Array) {
            for (var i = 0, len = eventArr.length; i & lt; len; i++) {
                if (typeof eventArr[i] === "function") {
                    eventArr[i](data);
                }
            }
        }
    }
}

这个还是以前写的代码,懒得写了,直接拿来用了,细心的你会发现,在实际代码中观察者和订阅者并没有区分开。对于once方法这里并没有实现,都很简单,如果要基于上面的代码实现once方法,有两种选择:通过再新加一个只触发一次的监听列表onceListeners将始终触发的和致出发一次的区分开,这种是比较简单的改法,或者是通过修改listeners内数据数据存储格式,可以修改为下面这种:

{type, fn, isOnce}

四、应用

观察者模式的应用还是蛮广泛的,除了上面讲的开播提醒及类似的功能,在nodejs中观察者模式也是非常的广泛,nodejs中很多模块都是基于观察者模式实现,并且node提供了EventEmmiter基类便于开发者实现基于观察者模式的模块或应用,其次在promise等实现中也能找到观察者模式的身影。

文末,附上一个基于观察者模式实现的鼠标滚轮监听,你可以猛戳这里预览在线效果。

  • 支付宝二维码 支付宝
  • 微信二维码 微信
相关文章