javascript 设计模式之单例模式

2018-08-28  本文已影响0人  帅李王者

单例模式的定义:保证一个类仅有一个实例,并提供一个全局访问他的访问点。

那么问题来了,我们如何保证一个类仅有一个实例呢,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。

在JavaScript里,实现单例的方式有很多种,其中最简单的一个方式是使用对象字面量的方法,其字面量里可以包含大量的属性和方法:

varmySingleton = {

property1: "something",

property2: "something else",

method1:function() {

console.log('hello world');

}

};

如果以后要扩展该对象,你可以添加自己的私有成员和方法,然后使用闭包在其内部封装这些变量和函数声明。只暴露你想暴露的public成员和方法,样例代码如下:

varmySingleton =function() {

/* 这里声明私有变量和方法 */

varprivateVariable = 'something private';

functionshowPrivate() {

console.log(privateVariable);

}

/* 公有变量和方法(可以访问私有变量和方法) */

return{

publicMethod:function() {

showPrivate();

},

publicVar: 'the public can see this!'

};

};

varsingle = mySingleton();

single.publicMethod();// 输出 'something private'console.log(single.publicVar);// 输出 'the public can see this!'

上面的代码很不错了,但如果我们想做到只有在使用的时候才初始化,那该如何做呢?为了节约资源的目的,我们可以另外一个构造函数里来初始化这些代码,如下:

varSingleton = (function() {

varinstantiated;

functioninit() {

/*这里定义单例代码*/

return{

publicMethod:function() {

console.log('hello world');

},

publicProperty: 'test'

};

}

return{

getInstance:function() {

if(!instantiated) {

instantiated = init();

}

returninstantiated;

}

};

})();

/*调用公有的方法来获取实例:*/

Singleton.getInstance().publicMethod();

知道了单例如何实现了,但单例用在什么样的场景比较好呢?其实单例一般是用在系统间各种模式的通信协调上,下面的代码是一个单例的最佳实践:

varSingletonTester = (function() {

//参数:传递给单例的一个参数集合functionSingleton(args) {

//设置args变量为接收的参数或者为空(如果没有提供的话)varargs = args || {};

//设置name参数this.name = 'SingletonTester';

//设置pointX的值this.pointX = args.pointX || 6;//从接收的参数里获取,或者设置为默认值//设置pointY的值this.pointY = args.pointY || 10;

}

//实例容器varinstance;

var_static = {

name: 'SingletonTester',

//获取实例的方法//返回Singleton的实例getInstance:function(args) {

if(instance === undefined) {

instance =newSingleton(args);

}

returninstance;

}

};

return_static;

})();

varsingletonTest = SingletonTester.getInstance({ pointX: 5 });

console.log(singletonTest.pointX);// 输出 5

其它实现方式

方法1:

functionUniverse() {

// 判断是否存在实例if(typeofUniverse.instance === 'object') {

returnUniverse.instance;

}

// 其它内容this.start_time = 0;

this.bang = "Big";

// 缓存Universe.instance =this;

// 隐式返回this}

// 测试varuni =newUniverse();

varuni2 =newUniverse();

console.log(uni === uni2);// true

方法2:

functionUniverse() {

// 缓存的实例varinstance =this;

// 其它内容this.start_time = 0;

this.bang = "Big";

// 重写构造函数Universe =function() {

returninstance;

};

}

// 测试varuni =newUniverse();

varuni2 =newUniverse();

uni.bang = "123";

console.log(uni === uni2);// trueconsole.log(uni2.bang);// 123

方法3:

functionUniverse() {

// 缓存实例varinstance;

// 重新构造函数Universe =functionUniverse() {

returninstance;

};

// 后期处理原型属性Universe.prototype =this;

// 实例instance =newUniverse();

// 重设构造函数指针instance.constructor = Universe;

// 其它功能instance.start_time = 0;

instance.bang = "Big";

returninstance;

}

// 测试varuni =newUniverse();

varuni2 =newUniverse();

console.log(uni === uni2);// true

// 添加原型属性Universe.prototype.nothing =true;

varuni =newUniverse();

Universe.prototype.everything =true;

varuni2 =newUniverse();

console.log(uni.nothing);// trueconsole.log(uni2.nothing);// trueconsole.log(uni.everything);// trueconsole.log(uni2.everything);// trueconsole.log(uni.constructor === Universe);// true

方式4:

varUniverse;

(function() {

varinstance;

Universe =functionUniverse() {

if(instance) {

returninstance;

}

instance =this;

// 其它内容this.start_time = 0;

this.bang = "Big";

};

} ());

//测试代码vara =newUniverse();

varb =newUniverse();

alert(a === b);// truea.bang = "123";

alert(b.bang);// 123

上一篇下一篇

猜你喜欢

热点阅读