设计模式-单例模式
单例模式的定义:保证一个类仅有一个实例,并能够被全局访问。
单例模式在开发中应用非常广泛,比如网站的登录浮窗,当我们单击登录按钮的时候,页面中会出现一个登录浮窗,这个登录浮窗是唯一的,无论单击多少次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗就适合用单例模式来创建
单例模式
下面使用单例模式创建一个DIV节点
// 用于创建DIV的类
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) {
return instance || (instance = new CreateDiv(html));
}
})();
// 测试
var a = new ProxySingletonCreateDiv('sven1');
var b = new ProxySingletonCreateDiv('sven2');
console.log(a == b) // true
无论实例化多少个ProxySingletonCreateDiv,最终都只创建一个div,这就是单例模式。CreateDiv用于实现逻辑操作,init方法是一个用于初始化的通用函数(根据实际业务场景),最后用一个闭包(ProxySingletonCreateDiv)保证实例的唯一性
惰性单例
惰性单例指的是在需要的时候才创建对象实例,这种技术在实际开发中非常有用。以登录浮窗为例,实现方式有两种:
- 在页面加载完成后创建好浮窗,然后隐藏,点击登录按钮时显示
- 在页面加载完成后浮窗未创建,第一次点击登录按钮时创建浮窗
第二种方法的好处是,如果用户只是浏览网站,根本没打算登录,就可以少创建一个节点。
前面的单例模式是接近传统面向对象语言的实现,即单例对象从“类”中创建而来,这在面向对象的语言中是一种较好的实现方式,但JS本身并不是面向对象的语言,使用类的方式实现意义不大。下面结合JS的风格实现登录浮窗惰性单例
// 使用闭包,确保fn只会执行一次
var getSingle = function(fn) {
var result;
return function() {
return result || (result = fn.apply(this, arguments));
}
};
// 创建浮窗函数
var createSingleLoginLayer = getSingle(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 = createSingleLoginLayer();
loginLayer.style.display = 'block';
};
当用户首次点击登录按钮,createSingleLoginLayer函数会创建一个浮窗并显示,而后再点击时getSingle函数会判断是否已经创建过,确保只创建一次。这是一种通用的实现方式,比如在使用JSONP跨域时,会创建一个script标签,然后动态改变他的src值,只需要getSingle中的参数即可
var createSingleScript = getSingle(function() {
var script = document.createElement('script');
document.body.appendChild(script);
return script;
});
document.getElementById('getUserInfo').onclick = function() {
var sc = createSingleScript();
sc.src = 'https://test.com/api?callback=userinfo';
};
胖胖熊笔记,笔记已迁移