【第四章】单例模式

定义: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。在 JavaScript 开发中,单例模式的用途同样非常广泛。试想一下,当我们单击登录按钮的时候,页面中会出现一个登录浮窗,而这个登录浮窗是唯一的,无论单击多少次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗就适合用单例模式来创建。

核心:确保只有一个实例,并提供全局访问

  1. 实现单例模式

    用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    var Singleton = function(name){
    this.name = name
    this.instance = null //存放已经生成的实例对象
    }
    Singleton.prototype.getName = function(){
    console.log(this.name)
    }
    Singleton.getInstance = function(name){
    if(!this.instance){
    this.instance = new Singleton(name)
    }
    return this.instance
    }

    var a = Singleton.getInstance('doreen')
    var b = Singleton.getInstance('sherry')
    a.getName() //doreen
    b.getName() //doreen
    console.log(a === b) //true

  2. 透明的单例模式

    使用的时候要和普通类一样通过new去创建实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // 利用闭包的方式 让变量存在局部
    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;
    })()
    var a = new CreateDiv('doreen')
    var b = new CreateDiv('sherry')
    console.log(a === b) // true

  3. 用代理实现单例模式

    CreateDiv变成普通类,它跟proxySingletonCreateDiv组合起来可以达到单例模式的效果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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
    }
    })()

    var a = new proxySingletonCreateDiv('doreen')
    var b = new proxySingletonCreateDiv('sherry')
    console.log(a===b) // true

  4. 惰性单例

    是在需要的时候才创建对象实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /* 创建一个登录框  需要登录的时候才动态创建登录框*/
    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
    }
    })()

    var loginLayer = createLoginLayer()
  5. 通用的惰性单例

    惰性单例存在的问题

    1. 违反单一职责原则,创建对象和管理单例的逻辑都放在createLoginLayer对象内部
    2. 如果下次需要创建页面中唯一的iframe,或者script标签,用来跨域请求数据,就必须如法炮制,把createLoginLayer函数几乎照抄一遍
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      var createIframe = (function(){
      var iframe
      return function(){
      if(!iframe){
      iframe = document.createElement('iframe')
      iframe.style.display = 'none'
      document.body.appendChild(iframe)
      }
      return iframe
      }
      })()

      // 把代码抽离出来
      // 公用的部分 单例逻辑
      var getSingle = function(fn){
      var result
      return function(){
      return result || (result = fn.apply(this,arguments))
      }
      }
      // 创建对象的方法
      var createLoginLayer = function(){
      var div = document.createElement('div')
      div.innerHTML = '登录框'
      div.style.display = 'none'
      document.body.appendChil(div)
      return div
      }
      var createSingleLoginLayer = getSingle(createLoginLayer)

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2019-2023 John Doe
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信