单例模式的定义是:保证一个类仅有一个对象,并提供一个访问它的全局访问点。
根据定义我们可以实现一个简单的单例模式
不透明的单例模式
var Person = function(name) { this.name = name; } Person.getInstance = (function(){ var instance = null; return function(name) { if (!instance) { instance = new Person(name); } return instance; } })(); var person1 = Person.getInstance('1'); var person2 = Person.getInstance('2'); console.log(person1 === person2);
这个就是一个简单的单例,但是我们发现使用者必须直到Person是一个单例类,跟我们传统的new XXX()相比,增加了不透明性。
透明的单例模式
先看代码:
var Person = (function(){ var instance = null; var Person = function(name) { if (instance) { return instance; } this.name = name; this.sayName(); return (instance = this,instance); } Person.prototype.sayName = function(){ console.log(this.name); } return Person; })(); var person1 = new Person('1'); var person2 = new Person('2'); console.log(person1 === person2);
这里我们使用了匿名函数返回一个Person类,利用闭包和高阶函数,实现了一个透明的单例类Person,现在更符合我们传统的new XXX()形式创建类的实例。
但是我们上面介绍的单例模式更倾向于传统面向对象语言的实现,在JavaScript中根据单例的定义,我们应该利用js的特性,实现更符合js的单例模式。
JavaScript中的单例模式
在这里要说说全局变量的问题,例如window对象,我们在开发的时候就只使用一个window对象就可以了,在这里window就是JavaScript中的一个单例,在比如var a= {},在全局这个obj对象就是一个单例对象,但是在全局中,就会造成很多问题,比如我们后面重新定义了obj,那么就会覆盖掉之前的对象,这个就是全局变量带来的坏处。
为了解决这个问题,我们可以如下常见的方法来处理该问题:
// 使用命名空间 var nameSpace = { obj: {} } // 使用闭包 var _obj = (function(){ return { obj: {} } })()
现在我们来看一个全面的单例模式:
var Person = function() { return this; } var Animal = function(){ return this; } var SingleProxy = function(Func) { var instance = null; return function(){ return instance || (instance = new Func()); } } var CreatePerson = SingleProxy(Person); var person1 = new CreatePerson("ss"); var person2 = new CreatePerson('sss'); console.log(person1 === person2); var CreateAnimal = SingleProxy(Animal); var animal1 = new CreateAnimal("cat"); var animal2 = new CreateAnimal('dog'); console.log(animal1 === animal2);
在这里我提供了一个创建单例的基本模板,我们看来做了一些什么,
我们创建了SingleProxy函数,只要把想要实现单例的类放进去,就会得到一个单例,这样子一来我们就不需要关心类的内部代码是怎样子的(有点小神奇是吧)
当然正如我所说的,这个只是基础的模版,如果要引用实际中,还需要自己扩展,比如,我们要存一个文件,我们可以存到存储器a,也可以存到存储器b,但是为了计算机性能的考虑,我们在得到存储器a或者b的时候,为了节约空间,我们以后的文件最好都存储到两个存储器中的一个,不要在去得到新的存储器。
代码如下:
var CacheA = function () { this.caches = {}; this.setCache = function (key, value) { caches[key] = value; } this.getCache = function (key) { return caches[key]; } } var CacheB = function () { this.caches = {}; this.setCache = function (key, value) { caches[key] = value; } this.getCache = function (key) { return caches[key]; } } var SingleProxy = function (Func) { var instance = null; return function () { return instance || (instance = new Func()); } } var CreateCacheA = SingleProxy(CacheA); var cachea1 = new CreateCacheA(); var cachea2 = new CreateCacheA(); console.log(cachea1 === cachea1); var CreateCacheB = SingleProxy(CacheB); var cacheb1 = new CreateCacheB(); var cacheb2 = new CreateCacheB(); console.log(cacheb1 === cacheb2);
现在你就可以愉快存文件了。