本部分内容主要讲解JavaScript开发中常见的14中设计模式。
第二部分 设计模式
第 4 章 单例模式
单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点。
单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的window对象等。例如我们单击登录按扭的时候,页面中会出现一个浮窗,这个登录浮窗就是唯一的,无论单击多少次登录按扭,这个浮窗都只会被创建一次,这个登录浮窗就适合用单例模式来创建。
4.1 实现单例模式
单例模式的实现是用一个变量来标志当前是否已经为某个类创建过对象,如果创建过,则下一 次再获取该类实例时,直接返回之前创建的对象。
<script type="text/javascript"> //单例模式 var Singleton = function(name){ this.name = name; this.instance = null; } Singleton.prototype.getName = function(){ console.log(this.name); } //通过Singleton.getInstance来获取Singleton类的唯一对象,虽然简单,但是增加了这个类的‘不透明性’,Singleton类的使用者必须知道这是一个单例类。 Singleton.getInstance = function(name){ if(!this.instance){ this.instance = new Singleton(name); } return this.instance; } var a = Singleton.getInstance('name1'); var b = Singleton.getInstance('name2'); console.log(a===b) </script>
4.2 透明的单例模式
//单例类,在页面内创建唯一的div节点 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('div1'); var b = new CreateDiv('div2'); console.log(a,b)
4.3 用代理实现单例模式
//代理实现单例模式 let 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); } let ProxySingletonCreateDiv = (()=>{ var instance; return function( html ){ if(!instance){ instance = new CreateDiv( html); } return instance; } })(); var a = new ProxySingletonCreateDiv('div1'); var b = new ProxySingletonCreateDiv('div2'); console.log(a,b)
4.4 JavaScript中的单例模式
1、动态创建命名空间
必免全局变量,造成命名空间污染。
//动态创建命名空间 var myFun = {}; myFun.nameSpace = function(name){ var protoName = name.split('.'); var current = myFun; for(var i in protoName){ if(!current[protoName[i]]){ current[protoName[i]] = {}; } current = current[protoName[i]]; } } myFun.nameSpace('event'); myFun.nameSpace('dom.style'); console.log(myFun)
var myFun = { event:{}, dom:{ style:{} } }
2、使用闭包封装私有变量
//使用闭包封装私有变量 var user = (function(){ var _name = 'John'; var _old = '30'; return { getUserInfo:function(){ return _name+'-'+_old; } } })(); console.log(user.getUserInfo())
4.5 惰性单例
惰性单例,在合适的时候才创建对象,并且只创建唯一的一个,将创建对象和管理单例分布在两个不同的方法中。
//惰性单例 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('btn').onclick = function(){ var loginLayer = createLoginLayer() loginLayer.style.display = 'block' }
4.6 通用的惰性单例
//通用的惰性单例 var getSingle = function(fn){ let result return function(){ return result || (result = fn.apply(this,arguments)) } } var createDiv = function(){ var div = document.createElement('div') div.innerHTML = '我是登录浮窗' div.style.display = 'none' document.body.appendChild(div) return div } var createSingleDiv = getSingle(createDiv) document.getElementById('btn').onclick = function(){ console.log('div') var div = createSingleDiv() div.style.display = 'block' }
//创建iframe var createFrame = function(){ var iframe = document.createElement('iframe') document.body.appendChild(iframe) return iframe } var createSingleIFrame = getSingle(createFrame) document.getElementById('btn').onclick = function(){ var iframe = createSingleIFrame() iframe.src = 'http://baidu.com' }
//绑定click单例 var bindEvent = getSingle(function(){ document.getElementById('btn').onclick = function(){ console.log('click') } return true }) var render = function(){ console.log('开始渲染') bindEvent() } render() render() render()