• 使用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);

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

  • 相关阅读:
    IIS6.0服务器架站无法访问解决方案总结
    DNN中做支持多语言的模块
    在dotnetnuke中创建 parent portal
    DNN,Rainbow资源
    2005年岁末,各种主流CMS系统的比较和汇总
    在DNN中获取所有模块信息
    学习dnn的新资源,sooooooooo great!!
    DNN的电子商务模块
    DNN学习笔记
    也学ASP.NET 2.0 AJAX 之二:使用Timer控件
  • 原文地址:https://www.cnblogs.com/jsydb/p/12520576.html
Copyright © 2020-2023  润新知