单例(SIngleton)模式:
功能: 用来划分命名空间:
1.减少网页中的全局变量的数量。
2.可以在多人开发时避免代码命名冲突。
3.一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。单例模式就是用一个命名空间包含自己的所有代码的全局对象。在传统工程师眼中,单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。示例:
1.对象字面量方法
1 var functionFree = { 2 name:'free', 3 method:function(){ 4 //code 5 }, 6 init:function(){ 7 //code 8 } 9 }
或者:使用实例化构造函数的方法
1 var functionFree = new function myGroup(){ 2 this.name = 'free', 3 this.getName = function(){ 4 5 } 6 ... 7 }
立即执行函数创建单体:
1 var Singleton = function(){//这个匿名函数返回一个对象,将这个对象//赋值给Singleton 2 return {}; 3 }(); 4 5 var Singleton = (function(){//这是声明之后立即调用 6 return {}; 7 }()); 8 9 var Singleton = (function(){//这是声明之后立即调用 10 return {}; 11 })();
2.扩展:如果要扩展对象,可以自定义私有成员和方法,然后使用闭包在内部封装这些变量和函数。暴露你想暴露的方法。
闭包实现内部方法外部调用。这种模式又叫做模块模式(module pattern)。
1 var mySingleton = function () { 2 /* 这里声明私有变量和方法 */ 3 var privateVariable = 'something private'; 4 function showPrivate() { 5 console.log(privateVariable); 6 } 7 /* 公有变量和方法(可以访问私有变量和方法) */ 8 return { 9 publicMethod: function () { 10 showPrivate(); 11 }, 12 publicVar: 'the public can see this!' 13 }; 14 }; 15 var single = mySingleton(); 16 single.publicMethod(); // 输出 'something private' 17 console.log(single.publicVar); // 输出 'the public can see this!'
3.用公有方法调用单例,在需要的时候才来初始化。将单例的代码放在init()函数中,第一次调用的时候才会实例化。
1 var Singleton = (function () { 2 var instantiated; 3 function construct() {//将所有的单例代码放到这个construct函数中间来。这里不能从外部访问。我们需要一个公有的方法getInstance方法来返回这个方法。 4 /*这里定义单例代码*/ 5 var param = "free"; 6 method1 = function(){ 7 8 } 9 return { 10 publicMethod: function () { 11 console.log('hello world'); 12 }, 13 publicProperty: 'test' 14 }; 15 } 16 17 return { 18 getInstance: function () { 19 if (!instantiated) {//判断类是否实例化 20 instantiated = construct();//对象 21 } 22 return instantiated; 23 } 24 }; 25 })(); 26 27 /*调用公有的方法来获取实例:*/ 28 Singleton.getInstance().publicMethod();
其实单例一般是用在系统间各种模式的通信协调上,下面的代码是一个单例的最佳实践:
外围是一个立即调用的函数,然后是一个构造函数,通过new生成一个单例instance,通过getInstance()传递进去参数,同时调用单例。
var SingletonTester = (function () {
//参数:传递给单例的一个参数集合
function Singleton(args) {
//设置args变量为接收的参数或者为空(如果没有提供的话)
var args = args || {};
this.name = 'SingletonTester';
this.pointX = args.pointX || 6; //从接收的参数里获取,或者设置为默认值
this.pointY = args.pointY || 10;
}
//实例容器
var instance;
var _static = {
name: 'SingletonTester',
//获取实例的方法
//返回Singleton的实例
getInstance: function (args) {
if (instance === undefined) {
instance = new Singleton(args);//实例化成对象调用
}
return instance;
}
};
return _static;
})();
var singletonTest = SingletonTester.getInstance({ pointX: 5 });
console.log(singletonTest.pointX); // 输出 5
4>>分支:返回需要的对象,而不管具体含有多少对象。最终只实例化需要的对象。
1 Singleton = (function(){ 2 var objectA = { 3 method1:function(){...}, 4 method2:function(){...}, 5 }; 6 var objectB = { 7 method1:function(){...}, 8 method2:function(){...}, 9 }; 10 return (someCondition) ? objectA : objectB; 11 })();