單例模式: 目的是創(chuàng)建全局唯一可用的對象
var createMask = function(){
return document.body.appendChild( document.createElement(div));
}
$( 'button' ).click( function(){
var mask = createMask();
mask.show();
})
// 缺點: 那么每次調(diào)用createMask都會創(chuàng)建一個新的div,
var mask;
var createMask = function(){
if ( mask ) {
return mask;
}else{
mask = document,body.appendChild( document.createElement(div) );
return mask;
}
}
//這里函數(shù)內(nèi)改變了外界變量mask,而且mask是全局變量并不是非需不可趋箩;
var getSingle = (function(){
var single;
return function(fn){
return single || (single = fn.apply(this, arguments));
}
})()
// 使用
// 無論執(zhí)行多少次createSingleDiv(), 都只返回同一個div
var createSingleDiv = getSingle(function(){
return document.createElement('div')
})
/**
* 這種方法本質(zhì)上是緩存函數(shù)結(jié)果是鬼,并且限制函數(shù)只執(zhí)行一次。
* 這里使用單例主要是針對那些全局只有一個就可以的對象,多于1個就浪費(fèi)腮鞍。
*/
訂閱-發(fā)布者模式 (觀察者模式)
觀察者模式又叫發(fā)布訂閱模式(Publish/Subscribe),它定義了一種一對多的關(guān)系莹菱,讓多個觀察者對象同時監(jiān)聽某一個主題對象移国,這個主題對象的狀態(tài)發(fā)生變化時就會通知所有的觀察者對象,使得它們能夠自動更新自己道伟。
使用觀察者模式的好處:
- 支持簡單的廣播通信迹缀,自動通知所有已經(jīng)訂閱過的對象。
- 頁面載入后目標(biāo)對象很容易與觀察者存在一種動態(tài)關(guān)聯(lián)蜜徽,增加了靈活性祝懂。
- 目標(biāo)對象與觀察者之間的抽象耦合關(guān)系能夠單獨(dú)擴(kuò)展以及重用。
publish/subscribe 模式使用了一個主題/事件通道拘鞋,這個通道介于希望接收到通知(訂閱者)和激活事件的對象(發(fā)布者)之間砚蓬。目的是避免訂閱者和發(fā)布者之間產(chǎn)生依賴關(guān)系
/**
* publish/subscribe 實現(xiàn)
* topics = [
* { topic1: [ {token: '', func: func}, {token: '', func: func}, ...]},
* { topic2: [ {token: '', func: func}, {token: '', func: func}, ...]},
* ]
*/
var pubsub = {};
(function(q){
var topics = {},
subUid = -1;
//發(fā)布或廣播事件,包含特定的topics名稱和參數(shù)
q.publish = function(topic,args){
if(!topics[topic]){
return false;
}
var subscribers = topics[topic],
len = subscribers ? subscribers.length : 0;
while(len--){
subscribers[len].func(topic,args);
}
return this;
};
//通過特定的名稱和回調(diào)函數(shù)訂閱事件盆色,topic/event觸發(fā)時執(zhí)行事件
q.subscribe = function( topic, func){
if(!topics[topic]){
topics[topic] = [];
}
var token = (++subUid).toString();
topics[topic].push({
token: token,
func: func
})
return token;
};
//基于訂閱上的標(biāo)記引用灰蛙,通過特定topic取消訂閱
q.unsubscribe = function(token) {
for(var m in topics){
if(topics[m]){
for(var i = 0, j = topics[m].legnth; i < j; i++){
if(topics[m][i].token == token){
topics[m].splice(i, 1);
return token;
}
}
}
}
return this;
};
}(punsub))
/**
* * 使用上述實現(xiàn)示例. 消息處理程序
*/
var messageLogger = function( topics, data){
console.log('Logging: ' + topics + ":" + data);
}
//訂閱者監(jiān)聽訂閱的topic,一旦該topic廣播一個通知隔躲,訂閱者就調(diào)用回調(diào)函數(shù)
var subscription = pubsub.subscribe('inbox/newMessage', messageLogger);
//發(fā)布者負(fù)責(zé)發(fā)布程序感興趣的topic或通知
pubsub.publish('inbox/newMessage', 'hello world');
// or
pubsub.publish('inbox/newMessage', ['test','a','b','c']);
//or
pubsub.publish('inbox/newMessage', { sender: 'hello@google.com', body: 'hey again!'})