單例模式

單例設計模式:保證一個類僅有一個實例,而且提供一個訪問它的全局訪問點。有些對象只須要一個,這時可用單例模式。javascript

傳統的單例模式

  • 和new 建立對象的調用不同
  • 調用者要調用xxx.getInstance才能得到該單例
function Singleton(name) {
    this.name = name;
}
Singleton.getInstance = function (name) {
    if(this.instace){
        return this.instace;
    }else {
        this.instace = new Singleton(name);
        return this.instace;
    }
};
var a = Singleton.getInstance('a');
var b = Singleton.getInstance('b');
console.log(a===b); //true
複製代碼

"透明"的單例模式

  • 透明」的單例類,用戶從這個類中建立對象的時候,能夠像使用其餘任何普通類同樣
  • 直接 new 一個對象
  • 不能new 多個對象,擴展性很差
var instace;
function Person(name) {
    this.name = name;
    if (!instace) {
        instace = this;
    }
    return instace;
}

Person.prototype.getName = function () {
    console.log(this.name);
};
var a = new Person('a');
var b = new Person('b');
console.log(a===b);
複製代碼

代理模式建立單例模式

  • 代理模式:本身不去作,委託中間人作
  • Person是一個普通類,經過new Person能夠建立一個對象
  • 用代理模式建立CreateSinglePerson方法,經過new CreateSinglePerson能夠建立一個單例
function Person(name) {
    this.name = name;
}
Person.prototype.getName = function () {
    console.log(this.name);
};
var CreateSinglePerson = (function (name) {
    var instance;
    return function () {
        if (!instance) {
            instance = new Person(name);
        }
        return instance;
    };
})();
var a = new CreateSinglePerson('a');
var b = new CreateSinglePerson('b');
console.log(a === b);
var c = new Person('c');
var d = new Person('d');
console.log(c === d);
複製代碼

JavaScript中的單例模式

  • 單例模式的核心是確保只有一個實例,並提供全局訪問
  • 在JavaScript能夠經過直接建立一個對象來實現單例模式
  • 能夠用閉包的方式實現私有變量
let MyApp = {
  name:'app',
  getName:function() {
    console.log(this.name);
  }  
};
let MyApp2 = (function(){
    var _name = 'app';
    return {
        getName:function() {
            console.log(_name);
        } 
    }
})();
複製代碼

惰性單例

  • 惰性單例是指在須要的時候才建立
  • 🌰:調用render方法,建立A對象,能夠屢次調用render方法,A對象是單例的
var createA = (function () {
    var instance;
    return function () {
        if(!instance){
            //xxx
            instance = 'A';
        }
        return instance;
    };
})();
function render() {
    createA();
    console.log('b');
}
render();
render();

複製代碼
  • 若是要建立B對象,B也是單例
var createB = (function () {
    var instance;
    return function () {
        if(!instance){
            //xxx
            instance = 'B';
        }
        return instance;
    };
})();
複製代碼
  • 咱們看到createA和createB的核心代碼是相同的,因此能夠抽離出通用建立的惰性單例的代碼
function getSingleton(fn) {
  var result;
  return function() {
    return result||(result = fn.apply(this,arguments));
  }
} 
var createA = function () {
    var instance;
    if(!instance){
        //xxx
        instance = 'A';
    }
    return instance;
};
var createB = function () {
    var instance;
    if(!instance){
        //xxx
        instance = 'B';
    }
    return instance;
};
var createASingle = getSingleton(createA);
var createBSingle = getSingleton(createB);
function render() {
    createASingle();
    createBSingle();
}
render();
render();

複製代碼

小結

單例模式用到了閉包和高階函數的特性。單例模式是簡單但經常使用到的模式,好比單頁應用、websocket鏈接等等。特別是惰性單例模式,用到時才建立,再次用到是不須要再次建立。建立對象和管理單例的職責分佈在不一樣的方法中,方便擴展和管理。java

參考
源碼
相關文章
相關標籤/搜索