单例模式: 目的是创建全局唯一可用的对象
var createMask = function(){
return document.body.appendChild( document.createElement(div));
}
$( 'button' ).click( function(){
var mask = createMask();
mask.show();
})
// 缺点: 那么每次调用createMask都会创建一个新的div,
var mask;
var createMask = function(){
if ( mask ) {
return mask;
}else{
mask = document,body.appendChild( document.createElement(div) );
return mask;
}
}
//这里函数内改变了外界变量mask,而且mask是全局变量并不是非需不可;
var getSingle = (function(){
var single;
return function(fn){
return single || (single = fn.apply(this, arguments));
}
})()
// 使用
// 无论执行多少次createSingleDiv(), 都只返回同一个div
var createSingleDiv = getSingle(function(){
return document.createElement('div')
})
/**
* 这种方法本质上是缓存函数结果,并且限制函数只执行一次。
* 这里使用单例主要是针对那些全局只有一个就可以的对象,多于1个就浪费。
*/
订阅-发布者模式 (观察者模式)
观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。
使用观察者模式的好处:
- 支持简单的广播通信,自动通知所有已经订阅过的对象。
- 页面载入后目标对象很容易与观察者存在一种动态关联,增加了灵活性。
- 目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。
publish/subscribe 模式使用了一个主题/事件通道,这个通道介于希望接收到通知(订阅者)和激活事件的对象(发布者)之间。目的是避免订阅者和发布者之间产生依赖关系
/**
* publish/subscribe 实现
* topics = [
* { topic1: [ {token: '', func: func}, {token: '', func: func}, ...]},
* { topic2: [ {token: '', func: func}, {token: '', func: func}, ...]},
* ]
*/
var pubsub = {};
(function(q){
var topics = {},
subUid = -1;
//发布或广播事件,包含特定的topics名称和参数
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;
};
//通过特定的名称和回调函数订阅事件,topic/event触发时执行事件
q.subscribe = function( topic, func){
if(!topics[topic]){
topics[topic] = [];
}
var token = (++subUid).toString();
topics[topic].push({
token: token,
func: func
})
return token;
};
//基于订阅上的标记引用,通过特定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))
/**
* * 使用上述实现示例. 消息处理程序
*/
var messageLogger = function( topics, data){
console.log('Logging: ' + topics + ":" + data);
}
//订阅者监听订阅的topic,一旦该topic广播一个通知,订阅者就调用回调函数
var subscription = pubsub.subscribe('inbox/newMessage', messageLogger);
//发布者负责发布程序感兴趣的topic或通知
pubsub.publish('inbox/newMessage', 'hello world');
// or
pubsub.publish('inbox/newMessage', ['test','a','b','c']);
//or
pubsub.publish('inbox/newMessage', { sender: '[email protected]', body: 'hey again!'})