js的单例模式

98 阅读2分钟

单例模式

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

1. 简单实现单例模式

var SingLeon = function(name){
  this.name = name
  this.instance = null
}

// 原型上定义方法getName
SingLeon.prototype.getName = function(){
console.log(this.name)
}

// 定义获取实例方法 如果存在实例,就返回该实例instance,否则新建一个

SingLeon.getInstance = function(){
  if(!this.instance){
    this.instance = new SingLeon()
  }
  return this.instance
}

var a = SingLeon.getInstance('s1')
var b = SingLeon.getInstance('s2')
console.log(a == b) // true

a和b都是同一个实例 但是有相应的缺点,使用者必须知道这是一个单例模式才能使用

2.使用代理实现单例模式

var SingLeon = function(name){
  this.name = name
  this.getName()
}

// 原型上定义方法getName

SingLeon.prototype.getName = function(){
console.log(this.name)
}

// 引入代理类
var proxy = (function(){
    var instance
      return function(name){
         if(!this.instance){
            instance = new SingLeon(name)
                  }
            }
        })()
}
var a = SingLeon.getInstance('s1')
var b = SingLeon.getInstance('s2')
console.log(a == b) // true

这样将管理的逻辑交给代理类proxy来解决了。SingLeon只是一个普通的方法了。

3.javaSrcipt的使用方式

  • 全局方式
    直接var a = {} 使用全局变量符合单例模式,window.a即可访问。但是全局的缺点就不说了
  • 使用命名空间
  a:function(){
    alert('1')
  }
  b:function(){
    alert('1')
  }
}

这样可以减少变量的使用。另外可以动态的创建全局变量。不在这里展示了。

  • 使用闭包
  var _name = 'name', _age = 29
  return {
    getUserInfo: function(){
      return _name + _age
    }
  }
})()

这样封装到了闭包的空间里,外部访问不到,避免全局变量污染

4.惰性单例

也是单例模式中最重要的,即最开始的时候使用instance就是惰性,在调用的时候才被创建,而不是一开始就创建 举出书上登陆qq的例子

// 创建登陆
var createLoginLayer = (function(){ 
var div; 
return function(){ 
// 判断是否创建过这个元素 也是重要的一点
if ( !div ){ 
div = document.createElement( 'div' ); 
div.innerHTML = '我是登录浮窗'; 
div.style.display = 'none'; 
document.body.appendChild( div ); 
} 
return div; 
} 
})(); 

这段代码依然有缺点,即违反单一职责原则 下次创建其他的元素,例如iframe等其他,仍然要如法炮制,重新复制一遍

var getSingle = function(Fn){
  var result;
  return function(){
    return result || (result = fn.apply(this, arguments))
  }
}

将创建任何的方法当参数传入getSingle,这样可以传入createDiv,createSrcipt等等。并用result保存,如果创建过result,则直接返回result

5.vue中使用

vue2中挂载全局方法 可以根据上述登录,实现一个登陆弹窗的方法。将来会写一下