單例模式,傳說中最簡單,最容易理解的設計模式
其實單例模式有很多方式去實現,下面我將書上所說一一展現
最簡單的實現方式
var Singleton = function (name) {
this.name = name;
this.instance = null; //暫存例項
}
Singleton.prototype.getName = function () {
alert(this.name)
}
Singleton.getInstance = function (name) {
if (!this.instance) { // 判斷例項是否存在
this.instance = new Singleton(name)
}
return this.instance
}
// 或者 getInstance 也可以用另一種方式實現
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) // true
複製程式碼
上面程式碼中
getInstance
方法用了兩種不同方式實現,但是原理都是一樣的,只不過是一個把例項屬性放在本例項內,一個是利用閉包放在區域性變數中。
這樣寫的方式有一個缺點,就是和正常的生成例項方法不一樣,讓人不容易理解
正常生成例項方法
var CreateDiv = (function () {
var instance = null;
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.append(div);
}
return CreateDiv
})();
複製程式碼
這種方法雖然能夠以new 去生成單例,但是建立物件和保證單例耦合在了一起,不符合單一職責原則。所以還要改
用代理實現單一模式
var CreateDiv = function (html) {
this.html = html;
this.init();
}
CreateDiv.prototype.init = function () {
var div = document.createElement('div');
div.innerHTML = this.html;
document.body.append(div);
}
var ProxySingletonCreateDiv = (function () {
var instance;
return function (html) {
if (!instance) {
instance = new CreateDiv(html);
}
return instance;
}
})();
複製程式碼
通過代理模式,創造物件和保證單例的方法分開,更易擴充套件
惰性單例
var createLoginLayer = function () {
var div = document.createElement('div');
div.innerHTML = '我是登入浮窗';
div.style.display = 'none';
document.body.appendChild(div);
return div;
}
var getSingle = function (fn) {
var result;
return function () {
return result || (result = fn.apply(this, arguments));
}
}
var createSingleLoginLayer = getSingle(createLoginLayer);
// 當需要呼叫的時候 再呼叫這個方法
複製程式碼
惰性單例的優點可以當我需要的再去建立這個單例,而不是頁面已載入就建立。