Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端必会设计模式之(六) 观察者模式 #9

Open
LyzSg opened this issue Jun 14, 2018 · 0 comments
Open

前端必会设计模式之(六) 观察者模式 #9

LyzSg opened this issue Jun 14, 2018 · 0 comments

Comments

@LyzSg
Copy link
Owner

LyzSg commented Jun 14, 2018

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

作为观察者的你,订阅了一些消息,被观察者在有消息的时候就会通知你,并且把消息给到你。这个模式存在的意义就是解耦,被观察者无需关心你如何处理消息。

事实上,只要你曾经在DOM节点绑定过事件函数,那么你就曾经使用过观察者模式了。它的另一个名字也称为自定义事件(custom events),与那些浏览器触发的事件相比,自定义事件是由你编写实现的事件。

此外,该模式也叫订阅/发布(subscriber / publisher)模式

于是我们事不宜迟,来实现一个简单的Event模块,其就有发布消息、订阅消息、退订消息等功能。

function Event() {
    // 首先他有一个订阅者列表,即存放事件类型和对应的回调
    this.cache = {};
}

接着我们来实现订阅:

Event.prototype.listen = function(type, handler) {
    if(!this.cache[type]) {
        // 如果列表中找不到对应的事件类型,则新增这个类型,并把他的所有回调作为数组赋值
        this.cache[type] = [handler];
    } else {
        // 如果有就直接添加回调
        this.cache[type].push(handler);
    }
}

再接着,我们来实现发布:

Event.prototype.emit = function (type) {

    // 做个容错处理,判断缓存中有无传入的事件类型
    if(!this.cache[type]) {
        throw 'no this type of event';
    }

    // 取得参数(可有可无)
    var args = Array.prototype.slice.call(arguments, 1);
    // 获取对应事件类型绑定回调的个数
    var len = this.cache[type].length;

    // 传入参数,执行回调
    for(var i = 0; i < len; i ++) {
        this.cache[type][i].apply(this, args);
    }
}

我们再添加一个退订的功能:

Event.prototype.remove = function (type, handler) {
    
    // 例行检查
    if(!this.cache[type]) {
        throw 'no this type of event';
    }

    // 筛选出除了handler以外的其他回调组成新的list[type]
    this.cache[type] = this.cache[type].filter(function (ele) {
        return ele != handler;
    })
}

至此,我们完成了一个简单的Event模块,接着我们来测试一下:

var oE = new Event();

// 订阅一个获取时间的东东
oE.listen('getTime', function (time) {
    console.log('Now is ' + time);
})
oE.listen('getTime', function (time) {
    console.log(time + ' is good');
})
// 发布当前时间
oE.emit('getTime', new Date());

image

没问题~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant