何爲單例模式?顧名思義,單例模式就是保證一個類僅有一個實例,也就是建立出來的兩個實例必須相等!html
function Singleton() { // 已有實例則返回該實例,沒有則建立實例 if (typeof Singleton.instance === 'object') { return Singleton.instance } // 把本身綁定到insta靜態屬性上,保證每次建立相同實例 Singleton.instance = this } var sigle1 = new Singleton() var sigle2 = new Singleton() console.log(sigle1 === sigle2) // true 兩個實例相等 sigle1.instance = 123 console.log(sigle2.instance) // 123
該方法的缺點是,instance屬性暴露外面,改變一個實例的屬性,另外一個也會跟着改變! 實例sigle1.instance的改變的同時sigle2.instance也跟着同時也變化了,這不是咱們但願要的結果!設計模式
const Singleton = function (name) { this.name = name this.instance = null } Singleton.getInstance = function (name) { // 單例已建立則返回,未建立則建立並返歸 return this.instance || (this.instance = new Singleton(name)) } Singleton.prototype.getName = function () { return this.name } var instance1 = Singleton.getInstance('instance1') var instance2 = Singleton.getInstance('instance2') console.log(instance1 === instance2) // true 兩個實例相等 console.log(instance1.getName(), instance2.getName()) // instance1 instance1
和上一個案例相似,利用構造函數的靜態熟悉存儲單例,可是該單例並不能改變instance屬性。然而,該方法建立單例具備不透明性,須要具體告知用戶如何使用。閉包
function Singleton() { var Man = function (name) { this.name = name } var instance // 函數中返回函數,且返回函數中佔用instance,造成閉包,instance惟一 return function (arg) { if (!instance) { instance = new Man(arg) } return instance } } var single = Singleton() console.log(single('tom') === single('jack')) // true 兩個實例相等
和上面一個案例同樣,用閉包建立單例具備不透明性,並且容易形成內存泄漏。好了說了這麼多實現單例的方式,接下來講說單例在工做中的具體使用狀況。app
咱們html頁面中的提示遮罩框就可使用單例來建立,由於建立一次,重複使用,不必再次建立相同遮罩框。這邊我就不寫具體遮罩框的樣式了,嘿嘿。函數
// 在html頁面建立點擊按鈕 <button id="app">點我建立單例</button>
// 利用當即執行函數建立遮罩框layer var creatLayer = (function(innerHTML){ var layer return function(innerHTML){ if(!layer){ layer = document.createElement('div') layer.innerHTML = innerHTML layer.style.display = 'none' document.body.appendChild(layer) } return layer } })() // 點擊按鈕彈出遮罩框 document.getElementById('app').onclick = function(){ var layer = creatLayer('我是遮罩框') layer.style.display = 'block' }
不管按鈕點擊多少次,始終只有建立一個遮罩框,從而避免重複建立。不過邊creatLayer函數中含有大量業務代碼。遵循高內聚,低耦合的思想,咱們進行改造!this
// 把業務代碼寫到creatLayer函數 var creatLayer = function (innerHTML) { var layer = document.createElement('div') layer.innerHTML = innerHTML layer.style.display = 'none' document.body.appendChild(layer) return layer } // 單例單例判斷交給getSingle函數,和業務邏輯分開 var getSingle = function (fn) { var div return function () { return div || (div = fn.apply(this, arguments)) } } var layer = getSingle(creatLayer) document.getElementById('app').onclick = function () { var div = layer('我是遮罩框') div.style.display = 'block' }
好了,單例模式具體介紹到這裏了。若是想看更多的設計模式,能夠看我晚期設計模式系列文章。若是以爲對你有幫助的話,記得給個贊哈😃prototype