定義
限制一個類只能有一個實例,並提供一個全局的單一訪問點。
簡單的單例模式
在 JS 中,可以通過對象字面量的方式去創建一個實例對象。
var singleton = {
prop1: 'foo',
prop2: 'bar',
method1: function() {
console.log(123)
}
}
上面就是一個簡單單例模式的示例。如果需要添加私有變量和方法,可以把等號右邊改成一個立即調用函數表達式。
到這裏,怎麼感覺和之前說的模塊模式差不多了。其實之前說的模塊模式就是一種簡單的單例模式。
但是這種簡單單例模式沒法推遲它們的初始化。下面我們看比較複雜的單例模式。
惰性單例
所謂惰性單例就是在用到的時候纔去初始化,那麼我們做一下優化。
var singleton = (function() {
var _instance
function Init() {
this.prop1 = 'foo'
this.prop2 = 'bar'
this.method1 = function() {
console.log(123)
}
}
return function () {
// 只實例化一次
if (!_instance) {
_instance = new Init()
}
return _instance
}
})()
// 使用
var instance1 = singleton()
var instance2 = singleton()
console.log(instance1 === instance2) // => true
上面的示例,首先使用了立即調用函數表達式,創建了獨立的作用域。其次在內部使用了構造函數,並返回一個函數賦值給全局變量 singleton
。在這個函數中對實例的存在進行了判斷,保證當前構造函數實例個數唯一。
只有在需要使用的時候,調用 singeton
函數,便會返回一個實例,而且每次調用返回的都是同一個實例。這就實現了惰性單例。
[擴展] ES6
我們用 ES6 的 class 來重寫下上面的單例模式。這裏採用調用靜態方法的方式來獲取實例。
class Singleton {
constructor() {
this.prop1 = 'foo'
this.prop2 = 'bar'
}
method1 () {
console.log(123)
}
// 靜態方法
static getInstance() {
if (!this.instance) {
this.instance = new Singleton()
}
return this.instance
}
}
// 使用
const instance1 = Singleton.getInstance()
const instance2 = Singleton.getInstance()
console.log(instance1 === instance2) // => true
以上就是單例模式的內容。