JS实现观察者模式(订阅/发布模式)

实现

/*
 * js 观察者模式 又称 订阅/发布模式
 * 通过创建“可观察”对象,当发生一个感兴趣的事件时可将该事件通告给
 * 所有观察者,从而形成松耦合
*/

// 通用的发布者
EventPublisher = Base.extend({
	publish: function(data, type) {
		EventPublisher.publish(data, type);
	}
}, {
	subscribers : {
        any : []    // 事件类型: 订阅者
    },

    // 将订阅者提供的调用方法添加到subscribers 订阅的事件数组中
    subscribe : function(subscriber) {
        var type = subscriber.type || ‘any‘;
        if (typeof this.subscribers[type] === ‘undefined‘) {
            this.subscribers[type] = [];
        }
        this.subscribers[type].push(subscriber.handleEvent);
    },

    // 删除订阅者
    unsubscribe : function(fn, type) {
        this.visitSubscribers(‘unsubscribe‘, fn, type);
    },

    // 循环遍历subscribers中每个元素,并调用他们所提供的方法
    publish : function(publication, type) {
        this.visitSubscribers(‘publish‘, publication, type);
    },

    // helper
    visitSubscribers: function (action, arg, type) {
        var pubtype = type || ‘any‘,
            subscribers = this.subscribers[pubtype],
            i,
            max = subscribers.length;
        for (i = 0; i < max; i += 1) {
            if (action === ‘publish‘) {
                // 调用订阅者订阅该事件所提供的方法
                subscribers[i](arg);
            } else {
                // 找到当前订阅事件中提供的方法,并删除
                if (subscribers[i] === arg) {
                    subscribers.splice(i, 1);
                }
            }
        }
    }
});

测试

// 实现paper 对象,他所做的就是发布日刊和月刊
Paper = EventPublisher.extend({
    daily : function() {
        this.publish(‘今个有重要新闻‘, ‘paper-daily‘);
    },
    monthly : function() {
        this.publish(‘每月调查‘, ‘paper-monthly‘);
    },
	readWeibo: function(info) {
		console.log(‘重大新闻[‘ + info + ‘]‘);
	}
});

// 订阅者对象joe,该对象有2个方法
Person = EventPublisher.extend({
	name: null,
	constructor: function(config) {
		this.name = config.name;
	},
    drinkCoffee : function(paper) {
        console.log(this.name + ‘开始阅读[‘ + paper + ‘]‘);
    },
    sundayPreNap : function(monthly) {
        console.log(this.name + ‘开始阅读[‘ + monthly + ‘]‘);
    },
	weibo: function(msg) {
		this.publish(msg, ‘person-weibo‘);
	}
});

var paper = new Paper();
var darkness = new Person({
	name: ‘darkness‘
});

EventPublisher.subscribe({
	type: ‘paper-monthly‘,
	handleEvent: function(data) {
		darkness.sundayPreNap(data);
	}
});

EventPublisher.subscribe({
	type: ‘paper-daily‘,
	handleEvent: function(data) {
		darkness.drinkCoffee(data);
	}
});

EventPublisher.subscribe({
	type: ‘person-weibo‘,
	handleEvent: function(data) {
		paper.readWeibo(data);
	}
});

// paper开始发布日刊 和 月刊
paper.daily();
paper.monthly();

// darkness发布微博信息
darkness.weibo(‘今日头条,2015年啦!‘);

参考

一个javascript继承的基础类Base.js


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。