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.jsjavascript

相關文章
相關標籤/搜索