js常用算法1---單例模式

單例模式的定義:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點
1,簡單實現

var Singleton = function (name) {
    this.name = name
}
Singleton.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('a')
var b = Singleton.getInstance('b')
console.log(a === b)

或者:

var Singleton = function (name) {
  this.name = name
}
Singleton.prototype.getName = function () {
  console.log(this.name)
}
Singleton.getInstance = (function () {
  var instance = null
  return function (name) {
    if (!instance) {
      instance = new Singleton(name)
    }
    return instance
  }
})()

//所謂單例模式,就是隻有一個對象實例
var a = Singleton.getInstance('a')
var b = Singleton.getInstance('b')
console.log(a === b)

在這段代碼中,我們需要通過Singleton.getInstance來獲取Singleton的實例,使用者必須知道Singleton類是一個單例類,這增加了代碼的“不透明性”,通過Singleton.getInstance獲取對象的方式也與一般的new方法獲取不同。這段單例模式代碼的意義不大

2,透明的單例模式

 //透明的單例模式
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 () {
    //node裏面沒有document,會報錯
    var div = document.createElement('div')
    div.innerHTML = this.html
    document.body.appendChild(div)
  }
  return CreateDiv
})()
var a = new CreateDiv('a')
var a = new CreateDiv('b')

現在我們實現了一個透明的單例類的編寫,但仍有一些問題
CreateDiv類中實際上有兩個功能:創建對象和執行初始化init方法、保證只有一個對象。不符合單一職責原則。
當我們需要取消單例,變成一個正常的構造函數時,修改代碼會帶來一些不必要的麻煩

3,透明單例改-代理模式

// 用代理實現代理模式
var CreateDiv = function (html) {
    this.html = html
    this.init()
}
CreateDiv.prototype.init = function () {
    var div = document.createElement('div')
    CreateDiv.innerHtml = this.html
    document.body.appendChild(div)
}

var ProxySingletonCreateDiv = (function () {
    var instance
    return function (html) {
        if (!instance) {
            instance = new CreateDiv(html)
        }
        return instance
    }
})()
var a = ProxySingletonCreateDiv('a')
var b = ProxySingletonCreateDiv('b')
console.log(a === b)

現在,負責管理單例的的邏輯在ProxySingletonCreateDiv中實現,CreateDiv就是一個普通的類,美滋滋

4,惰性單例
惰性單例指的是在需要的時候才創建對象實例。惰性單例是單例模式的重點。
在javaScript中,基於類的單例模式並不適用,需要轉變思路
4.1,彈框功能

var loginLayer = (function () {
    var div = document.createElement('div')
    div.innerHTML = '我要登錄,不給就送'
    div.style.display = 'none'
    document.body.appendChild(div)
    return div
})()
document.getElementById('loginBtn').onclick = function () {
    loginLayer.style.display = 'block'
}

缺點:loginLayer在頁面進來之後就直接執行了,如果用戶不需要這個彈框,很浪費

4.2,彈框功能節約版

var createLoginLayer = function () {
     var div = document.createElement('div')
     div.innerHTML = '我要登錄,不給就送'
     div.style.display = 'none'
     document.body.appendChild(div)
     return div
 }
 document.getElementById('loginBtn').onclick = function () {
     var loginLayer = createLoginLayer()
     loginLayer.style.display = 'block'
 }

雖然節約了,但是每次點擊的時候都會創建新的div,失去了單例的效果

4.3,彈框功能單例版

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
    }
})()
document.getElementById('loginBtn').onclick = function () {
    var loginLayer = createLoginLayer()
    loginLayer.style.display = 'block'
}

確實實現了單例的功能,但是彈框的創建和管理(if(!div) return div這段控制返回的代碼)都在createLoginLayer中實現,違反了單一職責原則

4.4,彈框功能OK版

 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.appendChild(div)
    return div
}
var createSingleLoginLayer = getSingle(createLoginLayer)
document.getElementById('loginBtn').onclick = function () {
    var loginLayer = createSingleLoginLayer()
    loginLayer.style.display = 'block'
}

good!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章