概念
单例模式: 只有一个实例存在。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统的资源。
基本结构
原始型:最简单的单例模式其实就是一个对象字面量。
var singleton = {
prop: "value",
method: function () {
}
}
这种形式的单例模式,所有成员都是公开的,都可以通过singleton来访问。这样的缺点是:单例中有一些辅助方法并不希望暴露给使用者,如果使用者用了这些方法,然后在后面维护的时候,一些辅助方法被删除,这样会造成程序的错误。
包含私有成员的单例模式
var singleton = (function () {
var privateVar = "private";
return {
prop: "value",
method: function () {
console.log(privateVar);
}
}
})();
首先是一个自执行的匿名函数,在匿名函数中,声明了一个变量privateVar,返回一个对象赋值给单例对象singleton。在匿名函数外部无法访问到privateVar变量,它就是单例对象的私有变量,只能在函数内部或通过暴露出来的方法去访问这个私有变量。这种形式又被成为模块模式。
惰性实例化
不管是直接字面量或者私有成员的单例模式,两者都是在脚本加载时就被创建出来的单例,但是有时候,页面可能永远也用不到这个单例对象,这样会造成资源浪费。对于这种情况,最佳的处理方式就是惰性加载,就是说在需要的时候才去真正实例化这个单例对象,如何实现呢?
var singleton = (function () {
function init() {
var privateVar = "private";
return {
prop: "value",
method: function () {
console.log(privateVar);
}
}
}
var instance = null;
return {
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
}
}
})();
首先将创建单例对象的代码封装到init函数中,然后声明一个私有变量instance表示单例对象的实例,公开一个方法getInstance来获取单例对象。
调用的时候就通过singleton.getInstance()来进行调用,单例对象是在调用getInstance的时候才真正被创建。
总结
单例模式的好处在于对代码的组织作用,将相关的属性和方法封装在一个不会被多次实例化的对象中,让代码的维护和调试更加轻松。隐藏了实现细节,可以防止被错误修改,还防止了全局命名空间的污染。另外可以通过惰性加载提高性能,减少不必要的内存消耗。