设计模式
一、单例模式
不透明单例
var Singleton = function(name) { this.name = name; this.instance = null; }; Singleton.prototype.getName = function(name) { alert(this.name); }; Singleton.getInstance = function(name) { if(!this.instance) { this.instance = new Singleton(name); } return this.instance; }; var a = Singleton.getInstance('tete1'); var b = Singleton.getInstance('tete2');
or
var Singleton = function(name) { this.name = name; }; Singleton.prototype.getName = function() { alert(this.name); }; Singleton.getInstance = (function(name) { var instance = null; return function(name){ if(!instance) { instance = new Singleton(name); } return instance; } })(); var a = Singleton.getInstance('test1'); var b = Singleton.getInstance('test2'); alert(a===b);
透明单例
var CreateDiv = (function() { var instance; var CreateDiv = function(html){ if(instance) {return instance;} this.html = html; this.init(); return instance = this; }; CreateDiv.prototype.init = function() { var div = document.createElement('div'); div.innerHTML = this.html; document.body.appendChild(div); }; return CreateDiv; })(); var a = new CreateDiv('seve1'); var b = new CreateDiv('seve2'); alert(a===b);
用代理实现单例模式
var CreateDiv = function(html){ this.html = html; this.init(); }; CreateDiv.prototype.init = function() { var div = document.createElement('div'); div.innerHTML = this.html; document.body.appendChild(div); }; var ProxySingletonCreateDiv = (function() { var instance; return function(html) { if(!instance) { instance = new CreateDiv(html); } return instance; } })(); var a = new ProxySingletonCreateDiv('seve1'); var b = new ProxySingletonCreateDiv('seve2'); alert(a===b);
惰性单例
var createLoginLayer = (function() { var div; return function() { if(!div){ div = document.createElement('div'); div.innerHTML = '我是登录浮窗'; div.style.display = 'none'; document.body.appendChild(div); } return div; } })(); document.getElementById('loginBtn').onclick = function() { var loginLayer = createLoginLayer(); loginLayer.style.display = 'block'; };
通用的惰性单例
var getSingle = function(fn){ var result; return function(){ return result || (result = fn.apply(this, arguments)); }; }; //创建浮窗
var createLoginLayer = function() { var div = document.createElement('div'); div.innerHTML = '我是登录浮窗'; div.style.display = 'none'; document.body.appendChild(div); return div; }; var createSingleLoginLayer = getSingle(createLoginLayer); document.getElementById('loginbtn').onclick = function() { var loginLayer = createSingleLoginLayer(); loginLayer.style.display = 'block'; };
//创建iframe动态加载第三方页面
var createSingleIframe = getSingle(function() {
var iframe = document.createElement('iframe');
document.body.append(iframe);
return iframe;
});
document.getElementById('loginbtn').onclick = function() {
var loginLayer = createSingleIframe();
loginLayer.src = 'http://knightboy.cn';
};
//给渲染列表绑定click事件 | //jQuery表示
var bindEvent = getSingle(function() { |var bindEvent = function() {
document.getElementById('div1').onclick = function(){ $('div').one('click',function(){
alert('click'); alert('click');
} });
return true; };
});
var render = function() {
console.log('开始渲染列表');
bindEvent();
};
render();
render();
render();
二、发布订阅模式
//发布订阅模式的通用实现 var event = { clientList: [], listen: function(key, fn){ if(!this.clientList[key]){ this.clientList[key] = []; } this.clientList[key].push(fn); }, trigger: function(){ var key = Array.prototype.shift.call(arguments), fns = this.clientList[key]; if(!fns || fns.length === 0) return false; for(var i=0,fn;fn = fns[i++];){ fn.apply(this, arguments); } }, remove: function(key, fn){ var fns = this.clientList[key]; if(!fns) return false; if(!fn) fns&&(fns.length === 0); else { for(var l=fns.length-1;l>=0;l--) { var _fn = fns[l]; if(_fn===fn) fns.splice(l,1); } } } }; var salesOffices = {}; var installEvent = function(obj){ for(var i in event){ obj[i] = event[i]; } }; installEvent(salesOffices); salesOffices.listen('squareMeter88', fn1=function(price){ console.log('价格= ' + price); }); salesOffices.listen('squareMeter88', fn2=function(price){ console.log('价格= ' + price); }); salesOffices.remove('squareMeter88',fn1); salesOffices.trigger('squareMeter88',2000000);
全局的发布订阅对象
var Event = (function() { var clientList = {}, listen, trigger, remove; listen = function(key, fn){ if(!clientList[key]){ clientList[key] = []; } clientList[key].push(fn); }; trigger = function(){ var key = Array.prototype.shift.call(arguments), fns = clientList[key]; if(!fns || fns.length === 0) return false; for(var i=0,fn;fn = fns[i++];){ fn.apply(this, arguments); } }; remove = function(key, fn){ var fns = clientList[key]; if(!fns) return false; if(!fn) fns&&(fns.length === 0); else { for(var l=fns.length-1;l>=0;l--) { var _fn = fns[l]; if(_fn===fn) fns.splice(l,1); } } }; return { listen: listen, trigger: trigger, remove: remove } })(); Event.listen('squareMeter88', function(price){ console.log('价格= ' + price); }); Event.trigger('squareMeter88',2000000); //价格= 2000000
全局事件的命名冲突处理
var Event = (function(){ var global = this, Event, _default = 'default'; Event = function(){ var _listen, _trigger, _remove, _slice = Array.prototype.slice, _shift = Array.prototype.shift, _unshift = Array.prototype.unshift, namespaceCache = {}, _create, find, each = function(ary, fn){ var ret; for(var i=0, l=ary.length;i<l;i++) { var n = ary[i]; ret = fn.call(n,i,n); } return ret; }; _listen = function(key, fn, cache){ if(!cache[key]) { cache[key]=[]; } cache[key].push(fn); }; _remove = function(key, cache, fn){ if(cache[key]){ if(fn){ for(var i=cache[key].length;i>=0;i--){ if(cache[key][i] === fn){ cache[key].splice(i, 1); } } }else{ cache[key] = []; } } }; _trigger = function(){ var cache = _shift.call(arguments), key = _shift.call(arguments), args = arguments, _self = this, ret, stack = cache[key]; if(!stack || !stack.length){ return; } return each(stack, function(){ return this.apply(_self, args); }); }; _create = function(namespace){ var namespace = namespace || _default; var cache = {}, offlineStack = [], //离线事件 ret = { listen: function(key, fn, last){ _listen(key, fn, cache); if(offlineStack === null){ return; } if(last === 'last') { offlineStack.length && offlineStack.pop()(); }else{ each(offlineStack, function(){ this(); }); } offlineStack = null; }, one: function(key, fn, last){ _remove(key, cache); this.listen(key, fn, last); }, remove: function(key, fn,){ _remove(key, cache, fn); }, trigger: function(){ var fn, args, _self = this; _unshift.call(arguments, cache); args = arguments; fn = function(){ return _trigger.apply(_self, args); }; if(offlineStack) return offlineStack.push(fn); return fn(); } }; return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret; }; return { create: _create, one: function(key, fn, last){ var event = this.create(); event.one(key, fn, last); }, remove: function(key, fn){ var event = this.create(); event.remove(key, fn); }, listen: function(key, fn, last){ var event = this.create(); event.listen(key, fn, last); }, trigger: function(){ var event = this.create(); event.trigger.apply(this,arguments); } }; }(); return Event; })();
/*************先发布后订阅****************/
Event.trigger('click', 1);
Event.listen('click', function(a){
console.log(a);//1
});
/*************使用命名空间***************/
Event.create('namespace1').listen('click', function(a){
console.log(a); //1
})
Event.create('namespace1').trigger('click', 1)
Event.create('namespace2').listen('click', function(a){
console.log(a); //2
})
Event.create('namespace2').trigger('click', 2)
三、享元模式
var Upload = function(uploadType) { this.uploadType = uploadType; }; Upload.prototype.delFile = function(id) { uploadManager.setExternalState(id, this); if (this.fileSize < 3000) { return this.dom.parentNode.removeChild(this.dom); } if (window.confirm("确定要删除吗? " + this.fileName)) { return this.dom.parentNode.removeChild(this.dom); } }; var UploadFactory = (function() { var createdFlyWeightObjs = {}; return { create: function(uploadType) { if (createdFlyWeightObjs[uploadType]) { return createdFlyWeightObjs[uploadType]; } return (createdFlyWeightObjs[uploadType] = new Upload(uploadType)); } }; })(); var uploadManager = (function() { var uploadDatabase = {}; return { add: function(id, uploadType, fileName, fileSize) { var flyWeightObj = UploadFactory.create(uploadType); var dom = document.createElement("div"); dom.innerHTML = "<span>文件名称: " + fileName + ", 文件大小: " + fileSize + "</span>" + '<button class="delFile">删除</button>'; dom.querySelector(".delFile").onclick = function() { flyWeightObj.delFile(id); };0 document.body.appendChild(dom); uploadDatabase[id] = { fileName: fileName, fileSize: fileSize, dom: dom }; return flyWeightObj; }, setExternalState: function(id, flyWeightObj) { var uploadData = uploadDatabase[id]; for (var i in uploadData) { flyWeightObj[i] = uploadData[i]; } } }; })(); var id = 0; window.startUpload = function(uploadType, files) { for (var i = 0, file; (file = files[i++]); ) { var uploadObj = uploadManager.add( ++id, uploadType, file.fileName, file.fileSize ); } }; startUpload("plugin", [ { fileName: "1.txt", fileSize: 1000 }, { fileName: "2.html", fileSize: 3000 }, { fileName: "3.txt", fileSize: 5000 } ]); startUpload("flash", [ { fileName: "4.txt", fileSize: 1000 }, { fileName: "5.html", fileSize: 3000 }, { fileName: "6.txt", fileSize: 5000 } ]);