使用JavaScript浅谈单例模式

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

根据定义我们可以实现一个简单的单例模式

不透明的单例模式

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);

现在你就可以愉快存文件了。

原文地址:https://www.cnblogs.com/jsydb/p/12520576.html