猫叔:Fighting!!!

JavaScript设计模式:单体模式

  单体模式:

    @单体模式用于创建命名空间,将系列关联的属性和方法组织成一个逻辑单元,减少全局变量。
      逻辑单元中的代码通过单一的变量进行访问。
    @一个单体对象由对象本身 和 访问这个对象的变量组成。
      此变量通常为全局变量,所以单体对象能在页面任何位置被访问,故此变量可看做单体对象内部属性和方法的一个命名空间。

    @三个特点:
      ① 该类只有一个实例;
      ② 该类自行创建该实例,即在该类内部创建自身的实例对象;
      ③ 向整个系统公开这个实例接口。
    @单体弊端:
      耦合度高,不好单元测试。

    @适合场合:
      提供命名空间,增加代码模块性,惰性加载,分支功能。

    1、基本结构:

var Singleton = {
    attr1 : 1,
    attr2 : 'hello',
    method1 : function(){alert(this.attr2);},
    method2 : function(arg){}
}

      1.1上例的方式,对象Singleton的所有成员是公开的,在执行到变量Singleton时,会加载(实例化)自身,即非惰性加载。
      1.2method1中用this访问单体的其他成员会存在一些风险,因为method1的上下文不是总指向Singleton对象。
        如,当方法绑定到事件监听器时,this指向dom元素而失效,这时会提示undefined,故最好使用单体对象的全名访问属性和方法。

    2、闭包 实现私有成员的单体,亦称为模块模式(module pattem)
      2.1闭包函数 返回的是一个字面量作为单体对象。在继承中返回的是一个构造函数,思路是一样的,利用闭包。
      2.2单体模式非常适合使用闭包实现私有方法,因为单体只会实例化一次,没有每次实例化都需要一份私有成员占用内存的顾虑。

var Singleton = (function(){
  var attr = 1, 
  fn = function(){};   return { //return的都是公有成员,其他私有     method : function(){ fn(); },     getAttr : function(){ return attr; }   }; })();

       2.3因为单体会被实例化一次,故构造函数中声明的所有成员值会被创建一次。
        上例,关键字var定义了私有成员,返回了一个公开的接口method和getAttr。
        今后,修改实现时只需修改私有成员,method和getAttr接口不变。

    3、闭包实现私有成员的惰性实例化单体,惰性实例化(lazy Instantiation)/惰性加载

      3.1前面提到的单体模式的实现 都是在脚本加载时即创建的。当一个单体对象需要加载大量数据时,在需要时再创建单体对象会更好。

      
      3.2单体放在constructor()函数中,getInstance函数用于控制单体加载。
        使用形式:MyNamespace.Singleton.getInstance().publicMethod1();
          对于长的命名空间可以用别名,var MNS = MyNamespace.Singleton;  可使用别名代替this!
        上述,用于需要大量数据的单体 直到需要时才实例化。对于命名空间、特定网页专用代码 和 实用的工具方法不使用。
        缺点:代码复杂,不直观。

     3、分支技术Branching:将浏览器之间的差异封装到动态方法,适用于解决浏览器之间的差异。

      

      通过return (someCondition) ? objectA : objectB;3
      缺点:分支中,objectA 和 objectB都被创建了,并保存在内存中了,但只用到一个。
        需要在 计算时间 和 占用内存 两者中取舍。

 

posted @ 2013-05-28 18:57  庄丶大虾  阅读(960)  评论(0编辑  收藏  举报