JS设计模式之单例模式篇

来源:互联网 发布:诺维斯基职业生涯数据 编辑:程序博客网 时间:2024/06/11 00:34

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

传统的创建单例的一种方式,用一个变量标识当前某个类是否已经创建对象,如果未创建,则新创建一个,否则返回已创建的那个对象

var Singleton=function(name){    this.name=name;}Singleton.prototype.getName=function(){    return this.name;}Singleton.getInstance=function(name){    if(!this.instance){        this.instance=new Singleton(name);    }    return this.instance;}测试:var a=Singleton.getInstance('mzz');var b=Singleton.getInstance('zzq');console.log(a===b);    //true

只要抓住用一个变量标识当前某个类是否已经创建对象这个思想,用js模仿传统的单例创建有多种方式。比如,上面这个例子是通过类的属性创建的对象,下面可以用new 创建对象的方式实现单例,这样可能看起来更像一个类。

var Singleton=(function(){    var instance;    function mySingle(name){        this.name=name;    }    mySingle.prototype.getName=function(){        return this.name;    }    return function(name){        if(!instance){            instance=new mySingle(name);        }        return instance;    }})();测试:var a=new Singleton("mzz");var b=new Singleton("zzq");console.log(a===b);   //true

我们完美的模仿了传统面向对象语言中的单例模式,但是对于js而言,可以说所有全局对象符合单例模式,我们看看下面这个对象

var obj={x:1,y:2};

它满足:
1. 仅有一个实例;
2. 提供一个全局的访问点;

虽然他能达到单例的效果,但是他有一个严重的问题,很容易造成命名空间污染,下面有两种方式可以降低全局变量的污染:

1.使用命名空间

  var myNamespace={};  myNamespace.obj={x:1,y:2};  myNamespace.obj2={x:3,y:4};

2.使用闭包封装私有变量

    var obj=(function(){        var _name="mzz",            _age="18";        return {            getName:function(){                return _name;            }            getAge:function(){                return _age;            }        }    })();

从上面的例子看出:对于javascript这门语言,生搬单例模式的概念并无意义。这也并不是说单例模式对于js没有意义,在js中,在某些情况我们还是需要用到它的,比如网站的登陆框,在用户没有点击登陆的时候他可以不存在,点击的时候才生成,这样可以避免在用户不需要登陆的时候,减少一个DOM节点的开销,但是如果每次登陆都要重新创建,那得到的结果反而是更加科学,此时单例模式就比较适合啦:

  1. 需要的时候才创建;
  2. 无论什么情况都只创建一次;
  document.getElementById('login').onclick=function(){        var loginDiv=new createLoginBox();        loginDiv.style.display='block';    }    var createLoginBox=(function(){        var div;        return function(){            if(!div){                div=document.createElement('div');                div.style.display="none";                document.body.appendChild(div);            }            return div;        }    })();

上面这个单例我们是针对登陆框写的,耦合性比较强,假如下次我们要使用单例模式创建iframe的时候,我们可能就是复制上面的大部分代码,然后改改少量不一样的东西,学设计模式就要有一些必要的思想,这个时候,我们再次看看代码,会发现,它存在违反单一指责原则,我们把管理单例和创建对象都放在了一个函数里实现的,下面我们把他们分离出来:

var createSingleLoginBox=new getSingle(createLoginBox);var createSingleFrame=new getSingle(createFrame);document.getElementById('login').onclick=function(){    var loginDiv=createSingleLoginBox();    loginDiv.style.display='block';}var getSingle=function(fn){    var result;    return function(){        return result||(result=fn.apply(this,arguments));    }};var createLoginBox=function(){    var div=document.createElement('div');    div.style.display="none";    document.body.appendChild(div);}var createFrame=function(){    var frame=document.createElement('frame');    frame.src="";    document.body.appendChild(frame);}

总结:在优化代码的时候,如果某个对象可以需要可以不需要,在需要的时候且只需做一次,那么我们可以考虑一下是否适合用这种单例模式,

0 0
原创粉丝点击