单例模式
1、单例模式
单例模式,顾名思义为它限制一个类只能有一个实例化对象。
var mySingleton = (function () { // 实例存储了对单例对象的引用 var instance; function init() { // 单例 // 私有方法和变量 function privateMethod(){ console.log( "I am private" ); } var privateVariable = "Im also private"; var privateRandomNumber = Math.random(); return { // 共有方法和变量 publicMethod: function () { console.log( "The public can see me!" ); }, publicProperty: "I am also public", getRandomNumber: function() { return privateRandomNumber; } }; }; return { // 如果存在获取此单例实例,如果不存在创建一个单例实例 getInstance: function () { if ( !instance ) { instance = init(); } return instance; } }; })(); var myBadSingleton = (function () { // 存储单例实例的引用 var instance; function init() { // 单例 var privateRandomNumber = Math.random(); return { getRandomNumber: function() { return privateRandomNumber; } }; }; return { // 总是创建一个新的实例 getInstance: function () { instance = init(); return instance; } }; })(); // 使用: var singleA = mySingleton.getInstance(); var singleB = mySingleton.getInstance(); var badSingleA = myBadSingleton.getInstance(); var badSingleB = myBadSingleton.getInstance();
那么:
singleA.getRandomNumber() === singleB.getRandomNumber() 一定成立;
badSingleA.getRandomNumber() === badSingleB.getRandomNumber()几乎不成立。
原因:
在badSingleA与 badSingleB实例化中,不论是否存在这样的实例,都重新创建实例,那么得到的随机数也不会相同。
在var singleA = mySingleton.getInstance()时,已经存储了对单例对象的引用的这样一个实例,那么再对singleB实例化时,这样的实例已经存在,不需要再创建新的实例,那么两个实例其实是一样的。
而这就是我们所说的单例模式,它允许一个类只能有一个实例化对象。
2、单例模式应用描述
i. 每个类只有一个实例,这个实例必须通过一个广为人知的接口,来被客户访问。
ii. 子类如果要扩展这个唯一的实例,客户可以不用修改代码就能使用这个扩展后的实例,比如:
mySingleton.getInstance = function(){ if ( this._instance == null ) { if ( isFoo() ) { this._instance = new FooSingleton(); } else { this._instance = new BasicSingleton(); } } return this._instance; };
不需要去更新每个访问单例的代码。FooSingleton可以是BasicSinglton的子类,并且实现了相同的接口。
3、高度抽象的单例模式 -- 惰性单例
惰性单例,意图解决:需要时才创建类实例对象。惰性单例也是解决 “按需加载” 的问题。
例如点击产生页面弹窗,多次点击都只有这一弹窗对象,内容不同而已。
//单例模式抽象,分离创建对象的函数和判断对象是否已经创建 var getSingle = function (fn) { var result; return function () { return result || ( result = fn.apply(this, arguments) ); } };
4、单例模式优缺点
优点:适用于单一对象,只生成一个对象实例,避免频繁创建和销毁实例,减少内存占用。
缺点:不适用动态扩展对象,或需创建多个相似对象的场景。