JavaScript的单例模式没有那么简单

想必大家都知道单例模式就是不管调用多少次new命令,始终只能创建一个实例对象。

写个方法来看看javaScript的单例长什么样。

下面这个例子是负责在页面中创建唯一的div节点。代码如下

var CreateDiv = (function(){
  var instance;
  var CreateDiv = function(html){
      if(instance){
        return instance;
      }
      this.html = html;
      this.init();
      return instance = this;
  }
  CreateDiv.prototype.init=function(){
     var div = document.createElement('div')
     div.innerHtml = this.html;
     document.body .appendChild(div)
  }
  return CreateDiv
})()

是不是跟你写的不太一样,是不是觉得这样写更好?

虽然这已经是优化过的js单例代码,但是他依然有缺点:

为了把instance封装起来,我们使用了自执行的匿名函数和闭包,并且让这个匿名函数返回真正的Singleton构造方法

这增加了一些程序的复杂度,阅读起来比较费劲。

观察这个Singleton构造函数

 var CreateDiv = function(html){
      if(instance){
        return instance;
      }
      this.html = html;
      this.init();
      return instance = this;
  }

它实际负责了两件事情1:创建对象和执行初始化init方法。2:保证只有一个对象。这与‘单一指责原则’违背

用代理模式实现单一职责的单例

var CreateDiv = function(html){
   this.html = html;
   this.init();
}
CreateDiv.prototype.init=function(){
   var div = document.createElement('div')
   div.innerHtml= this.html;
   document.body.appendChild(div);
}

接下来引入代理类proxySingletonCreateDiv

var ProxySingletonCreateDiv = (function(){
  var instance;
  return function(html){
     if(!instance){
       instance = new CreateDiv(html)
     }
     return instance
  }
})()

通过引入代理类的方式实现了单一职责的单例模式。噢耶~~~

CreateDiv只负责创建对象和初始化。ProxySingletonCreateDiv负责保证只有一个对象。

// 创建一个dog单例 来巩固一下
var Dog = function(name){
   this.name = name;
   this.init();
}
Dog.prototype.init=function(){
  console.log('I am dog, my name is '+this.name)
}
var ProxySingletonCreateDog = (function(name){
  var instance
  return function (name){
    if(!instance){
       instance = new Dog(name)
    }
    return instance
  }
})()

但是但是!上面的例子更多的接近传统的面向对象的语言实现,而javascript是一门无类语言,生搬单例模式并无意义  呜呜呜。

在javascript中创建单例模式非常的简单,既然我们只需要一个唯一的对象,为什么要为它创建一个类呢???这无异于穿衣服洗澡,传统的单例模式实现在JavaScript中并不适用!!

单例模式的核心1 保证只有一个实例2提供全局访问方法

全局变量不是单例模式,但是我们经常把全局变量当成单例来使用。

全局变量会造成命名空间污染,内存溢出等问题,所以尽量少使用全局变量。

我们可以使用闭包来实现单例

var User = (function(){
  var _name = 'stupidcc';
  var _age = 18;
  return {
     getName: function(){
        return _name 
     },
     getAge: function () {
        return _age
     },
     setAge: function(age){
        _age = age
     }
  }
})()

惰性单例

惰性是单例模式的重点,重点哦。

这种技术在开发过程中非常有用,有用程度可能超出了你的想象。

例如我们需要在页面中创建一个iframe,使用单例

// 代理
var getSingleton = function(fn){
   var result;
   return function (fn) {
     return result || (result = fn.apply(this,arguments))
   }
}
var initIframe = function () {
   var iframe = document.createElement('iframe')
   document.body.appendChild(iframe)
   return iframe
}
var CreateSingletonIframe = getSingleton(initIframe)
document.getElementById('button').onclick=function(){
   var iframeObj = CreateSingletonIframe()
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值