单例模式是什么?
创建型模式,提供了一种创建对象的最佳方式,这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。在应用程序运行期间,单例模式只会在全局作用域下创建一次实例对象,让所有需要调用的地方都共享这一单例对象。
从定义上来看,全局变量好像就是单例模式,但是一般情况我们不认为全局变量是一个单例模式,原因是:
- 全局命名污染
- 不易维护,容易被重写覆盖
单例模式如何实现?
ES5
var singleton = (function() {
var instance;
function init() {
// 单例代码
return {
// 公共方法和变量
publicMethod: function() {
console.log("Hello World!");
},
publicProperty: "test"
};
}
return {
// 获取单例实例的方法
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
};
})();
// 使用单例
var mySingleton = singleton.getInstance();
mySingleton.publicMethod();
ES6
class Singleton {
constructor() {
if (!Singleton.instance) {
// 单例代码
Singleton.instance = this;
}
return Singleton.instance;
}
// 公共方法和变量
publicMethod() {
console.log("Hello World!");
}
publicProperty = "test";
}
// 使用单例
const mySingleton = new Singleton();
mySingleton.publicMethod();
闭包
const singleton = (function() {
let instance;
function init() {
// 单例代码
return {
// 公共方法和变量
publicMethod: function() {
console.log("Hello World!");
},
publicProperty: "test"
};
}
return {
// 获取单例实例的方法
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
};
})();
// 使用单例
const mySingleton = singleton.getInstance();
mySingleton.publicMethod();
单例模式的应用场景?
在前端中,很多情况都是用到单例模式
应用实例
-
例如页面存在一个模态框的时候
只有用户点击的时候才会创建,而不是加载完成之后再创建弹窗和隐藏,并且保证弹窗全局只有一个。
-
Vuex、redux全局态管理库也应用单例模式的思想
-
现在很多第三方库都是单例模式,多次引用只会使用同一个对象,如
jquery、lodash、moment... -
有一些对象往往只需要有一个,比如线程池、全局缓存浏览器中的Windows对象等
项目实战
- 例如页面存在一个模态框
这种实现称为惰性单例,意图是只有当需要时才创建类实例对象
可以先创建一个通常的获取对象的方法,如下:
const getSingle = function( fn ){
let result;
return function(){
return result || ( result = fn .apply(this, arguments ) );
}
};
创建弹窗的代码如下:
const createLoginLayer = function(){
var div = document.createElement( 'div' );
div.innerHTML = '我是浮窗';
div.style.display = 'none';
document.body.appendChild( div );
return div;
};
const createSingleLoginLayer = getSingle( createLoginLayer );
document.getElementById( 'loginBtn' ).onclick = function(){
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = 'block';
};
总结
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。
优缺点
优点:
- 适用于单一对象,只生成一个对象实例,避免频繁创建和销毁实例,减少内存占用。
缺点:
- 不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
- 由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
- 单例类的职责过重,在一定程度上违背了“单一职责原则”。
最后一句
学习心得!若有不正,还望斧正。希望掘友们不要吝啬对我的建议。