网站首页  汉语字词  英语词汇  考试资料  写作素材  旧版资料

请输入您要查询的范文:

 

标题 JavaScript实现设计模式中的单例模式的一些技巧总结
范文
    单例模式是JavaScript项目中最常用的设计模式之一,下面罗列了JavaScript实现设计模式中的单例模式的一些技巧总结,包括惰性加载与分支技术等,需要的朋友可以参考下.
    一、使用全局变量保存单例
    这是最简单的实现方法
    function Person(){ 
      this.createTime=new Date(); 
    } 
    var instance=new Person(); 
    function getInstance(){ 
      return instance; 
    } 
    加载该js时就创建一个Person对象,保存到instance全局变量中,每次使用都取这个对象。如果一次都没使用,那么创建的这个对象则浪费了,我们可以优化一下,
    var instance 
    function getInstance(){ 
      if(!instance){ 
        instance=new Person(); 
      } 
      return instance; 
    } 
    这样,第一次使用时才创建对象。
    这个方法的缺点是,instance是全局的变量,在多人合作或者开发周期比较长的情况下,很难保证instance不会被其它代码修改或覆盖,很可能到调用的时候,发现instance根本就不是Person对象。
    我们考虑下使用闭包来封装起instance,使它不再是全局变量就可以解决这个问题了
    二、闭包创建对象
    var getInstance(){ 
    var instance; 
    return function(){ 
        if(!instance){ 
          instance=new Person(); 
        } 
        return instance; 
      } 
    }(); 
    这样,instance就被封装起来了,不用担心被修改了。
    现在通过getInstance()函数可以获得单例了。新的问题,如果我通过new Person()来创建对象,获得的还是多个对象,javascript又不可以像java一样把构造器私有化。那怎么样可以让多次new出来的对象都是一个实例呢?
    三、构造函数的静态属性缓存实例
    先看代码
    function Person(){ 
      //如果已经缓存了实例,则直接返回缓存的实例 
      if(typeof Person.instance==='object'){ 
        return Person.instance; 
      } 
      this.createTime=new Date(); 
      //缓存实例 
      Person.instance=this; 
      return this; 
    } 
    从代码可以看到,第一次new时,if的条件返回false,会往下走,初始化对象,然后保存对象到Person.instance这个静态属性中。
    第二次new 时,if的条件返回true,直接返回Person.instance,不会再往下运行初始化的代码。所以不管new几次,返回的都是第一次创建的对象。
    这个方法的缺点和方法一的缺点一样,Person.instance也是公开属性,有可能会被修改。
    我们参考方法二,使用闭包来封装一个,也许就能解决该问题了
    四、重写构造函数
    这个方法要使用闭包,但不能像方法二那么简单,我们需要重写构造函数。
    function Person(){ 
      //缓存实例 
      var instance=this; 
      this.createTime=new Date(); 
      //重写构造函数 
      Person=function(){ 
        return instance; 
      } 
    } 
    第一次new 时,调用原始构造函数先缓存该实例,然后再初始化,同时,重写该构造函数。以后再new 时,永远调用不到原始的构造函数了,只能调用到重写后的构造函数,而这个函数总是返回缓存的instance.
    上面的方法似乎没什么问题,但通过下面的测试,可以发现问题
    //向原型添加属性 
    Person.prototype.prop1=true; 
    var p1=new Person(); 
    //在创建初始化对象后,再次向该原型添加属性 
    Person.prototype.prop2=true; 
    var p2=new Person(); 
    //开始测试 
    console.log(p1.prop1);//结果为true 
    console.log(p2.prop1);//结果为true 
    console.log(p1.prop2);//结果为undefined 
    console.log(p2.prop2);//结果为undefined 
    console.log(p1.constructor===Person);//结果为false 
    console.log(p2.constructor===Person);//结果为false 
    我们预期中的结果,应该是全都是true。
    分析一下上述测试代码
    Person.prototype.prop1=true;是在原始构造函数的原型下增加了prop1这个属性,并赋值
    而在执行 var p1=new Person();之后,Person这个构造函数已经被重写了
    所以Person.prototype.prop2=true;是在新的原型下增加prop2这个属性
    var p2=new Person(); p2和p1实际上是同一个对象,即原始构造函数创建的对象
    所以p1 p2都有prop1这个属性,而没有prop2这个属性
    同样的,p1 p2的constructor指向的也是原始的构造函数,而Person此时已不是原来那个函数了
    为了能按预期的结果那样运行,可以通过一些修改来实现
    function Person(){ 
      //缓存实例 
      var instance=this; 
      //重写构造函数 
      Person=function(){ 
        return instance; 
      } 
      //保留原型属性 
      Person.prototype=this; 
      //实例 
      instance=new Person(); 
      //重置构造函数引用 
      instance.constructor=Person; 
      //其他初始化 
      instance.createTime=new Date(); 
      return instance; 
    } 
    再运行前面的测试代码,结果都是true了。
    五、惰性加载:
    在大型或复杂的项目中,起到了优化的作用:那些开销较大却很少用到的组件可以被包装到惰性加载单例中,示例程序:
    /* Singleton with Private Members, step 3. */
    MyNamespace.Singleton = (function() {
     // Private members.
     var privateAttribute1 = false;
     var privateAttribute2 = [1, 2, 3];
     function privateMethod1() {
      ...
     }
     function privateMethod2(args) {
      ...
     }
     return { // Public members.
      publicAttribute1: true,
      publicAttribute2: 10,
      publicMethod1: function() {
       ...
      },
      publicMethod2: function(args) {
       ...
      }
     };
    })();
    /* General skeleton for a lazy loading singleton, step 1. */
    MyNamespace.Singleton = (function() {
     function constructor() { // All of the normal singleton code goes here.
      // Private members.
      var privateAttribute1 = false;
      var privateAttribute2 = [1, 2, 3];
      function privateMethod1() {
       ...
      }
      function privateMethod2(args) {
       ...
      }
      return { // Public members.
       publicAttribute1: true,
       publicAttribute2: 10,
       publicMethod1: function() {
        ...
       },
       publicMethod2: function(args) {
        ...
       }
      }
     }
    })();
    /* General skeleton for a lazy loading singleton, step 2. */
    MyNamespace.Singleton = (function() {
     function constructor() { // All of the normal singleton code goes here.
      ...
     }
     return {
      getInstance: function() {
       // Control code goes here.
      }
     }
    })();
    /* General skeleton for a lazy loading singleton, step 3. */
    MyNamespace.Singleton = (function() {
     var uniqueInstance; // Private attribute that holds the single instance.
     function constructor() { // All of the normal singleton code goes here.
      ...
     }
     return {
      getInstance: function() {
       if(!uniqueInstance) { // Instantiate only if the instance doesn't exist.
        uniqueInstance = constructor();
       }
       return uniqueInstance;
      }
     }
    })();
    六、使用分支单例:
    针对特定环境的代码可以被包装到分支型单例中,示例程序:
    /* SimpleXhrFactory singleton, step 1. */
    var SimpleXhrFactory = (function() {
     // The three branches.
     var standard = {
      createXhrObject: function() {
       return new XMLHttpRequest();
      }
     };
     var activeXNew = {
      createXhrObject: function() {
       return new ActiveXObject('Msxml2.XMLHTTP');
      }
     };
     var activeXOld = {
      createXhrObject: function() {
       return new ActiveXObject('Microsoft.XMLHTTP');
      }
     };
    })();
    /* SimpleXhrFactory singleton, step 2. */
    var SimpleXhrFactory = (function() {
     // The three branches.
     var standard = {
      createXhrObject: function() {
       return new XMLHttpRequest();
      }
     };
     var activeXNew = {
      createXhrObject: function() {
       return new ActiveXObject('Msxml2.XMLHTTP');
      }
     };
     var activeXOld = {
      createXhrObject: function() {
       return new ActiveXObject('Microsoft.XMLHTTP');
      }
     };
     // To assign the branch, try each method; return whatever doesn't fail.
     var testObject;
     try {
      testObject = standard.createXhrObject();
      return standard; // Return this if no error was thrown.
     }
     catch(e) {
      try {
       testObject = activeXNew.createXhrObject();
       return activeXNew; // Return this if no error was thrown.
      }
      catch(e) {
       try {
        testObject = activeXOld.createXhrObject();
        return activeXOld; // Return this if no error was thrown.
       }
       catch(e) {
        throw new Error('No XHR object found in this environment.');
       }
      }
     }
    })();
随便看

 

在线学习网范文大全提供好词好句、学习总结、工作总结、演讲稿等写作素材及范文模板,是学习及工作的有利工具。

 

Copyright © 2002-2024 cuapp.net All Rights Reserved
更新时间:2025/5/14 16:05:30