单例模式是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
最后实现的效果:
例如:用户点击按钮的时候才显示弹框
让我们一步步优化,实现更好的单例模式
第一种:点击一次创建一个新对象
缺点 : 失去了单例的效果,当我们每次点击的时候都会创建一个新的div
<html>
<body>
<button id="loginBtn">登录</button>
</body>
<script>
var createLoginLayer = function(){
var 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';
};
</script>
</html>
第二种 :利用变量判断是否存在已经创建的登录浮窗
优点 : 惰性单例
缺点 :这段代码仍然是违反单一职责原则的,创建对象和管理单例的逻辑都放在 createLoginLayer对象内部。
<html>
<body>
<button id="loginBtn">登录</button>
</body>
<script>
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'; //显示弹框
};
</script>
</html>
第三种 :创建对象 与 管理单例模式的逻辑分开( 推荐)
优点 :管理单例的职责和创建对象实例的职责分别放在两个方法里,两个方法可以独立而互相不影响,当它们连接在一起的时候,就完成了创建唯一实例对象的功能,
<html>
<body>
<button id="loginBtn">登录</button>
</body>
<script>
// 管理单例的逻辑
var getSingle = function(fn){
var instance ; //保存在闭包中
return function(){
return instance || (instance = 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'; //显示弹框
};
</script>
</html>
无论点击多少次,只执行一次!!!
总结:在 getSinge 函数中,实际上也提到了闭包和高阶函数的概念。单例模式是一种简单但非常实
用的模式,特别是惰性单例技术,在合适的时候才创建对象,并且只创建唯一的一个。更奇妙的
是,创建对象和管理单例的职责被分布在两个不同的方法中,这两个方法组合起来才具有单例模
式的威力。