單例模式

單例模式

簡單的單例模式

經過一個getInstance方法獲取對象,首先判斷一個對象是否存在,若是存在則就將改對象返回,若是不存在就先實例化對象(建立對象),而後再返回javascript

將實例存儲在對象中

let Singleton = function(name){
  this.name = name;
}

// 將實例存儲在對象中
Singleton.getInstance = function() { 
  // 若是自己到
  if(this.instance === null){
    this.instance = new Singleton();
  }
  return this.instance;
}

let aIns = Singleton.getInstance("test");
let bIns = Singleton.getInstance("test");

console.log(aIns === bIns);

使用閉包存儲實例對象

// 將實例使用閉包的形式存儲起來
Singleton.getInstanceNew = (function() { 
  let instance = null;
  return function(){
    if(instance === null){
      instance = new Singleton();
    }
    return instance;
  } 
}())  

let cIns = Singleton.getInstanceNew("test");
let dIns = Singleton.getInstanceNew("test");

console.log(cIns === dIns, aIns === dIns);

咱們看到以上兩個方法,都是建立單例的簡單方法,雖然實現了,可是若是別人不知道這個對象時單例的,仍是可使用new關鍵字建立。而且再也不是單例了,因此很容易違背了咱們單例的初心html

透明的單例模式

咱們依然經過new建立實例,可是建立的仍是單例的,這樣即便不須要咱們特地去囑咐這個對象是單例前端

var TransparentSingleton = (function() {
   var instance = null;
   var TransparentSingleton = function(){
      if(instance){
        return instance;
      }
      this.init();
      return instance = this;
   } 

   TransparentSingleton.prototype.init = function(){
    console.log("Dom操做")
  }

  return TransparentSingleton;
}())


let eIns = new TransparentSingleton();
let fIns = new TransparentSingleton();

console.log(eIns === fIns);

這種方法雖然知足了咱們的要求,可是這裏存在一個問題,就是內部的TransparentSingleton的這對象,成爲了一個私有對象,咱們在外面沒法訪問到java

代理版單例模式

var CreateDom = function(html){
  this.html = html;
  this.init();
}

CreateDom.prototype.init = function(){
  console.log(this.html);
}

var ProxyCreateDom = (function(){
  let instance = null;
  return function(html){
    if(instance === null){
      instance = new CreateDom(html);
    }
    return instance;
  }
}())

let hIns = new ProxyCreateDom("測試");
let gIns = new ProxyCreateDom("前端");
console.log(hIns === gIns, hIns.html, gIns.html)

這裏咱們將對象提了出來了,經過ProxyCreateDom去建立一個關於CreateDom的單例,可是這個版本是比較有限的,咱們能夠看到這個代理單例並非一個可複用的,代碼極可能會翻倍。而且無論咱們需不要單例,其實ProxyCreateDom裏的instance就建立了。而且這個是屬於傳統面嚮對象語言的,在JavaScript這個沒有類的語言中,這樣建立意義並不大閉包

惰性單例模式通用版本

let getSingleton = function(func) { 
  let result = null;
  return function(){ 
    return result || (result = func.apply(this, arguments));
  }
}

function createLoginLayer(){
  var div = document.createElement("div");
  div.innerHTML = "我是登陸浮窗";
  div.style.display = "none";
  document.body.appendChild(div);
  return div;
}

/**
 * 測試代碼 
 */
let createSingleLoginLayer = getSingleton(createLoginLayer); 
// 添加一個登錄浮窗
document.getElementById("loginTest").onclick = function(){
  var loginLayer = createSingleLoginLayer();
  loginLayer.style.display = "block"
}
// 建立一個iframe的單例
var createSingleIfame = getSingleton(function () {
  var iframe = document.createElement("iframe");
  document.body.appendChild(iframe);
  return iframe;
})
// 建立一個iframe,並將src屬性設置爲百度
document.getElementById("loginBtn").onclick = function(){
  var loginLayer = createSingleIfame();
  loginLayer.src = "http://baidu,com";
}
// 將浮窗單例隱藏
document.getElementById("closeLoginBtn").onclick = function(){
  var loginLayer = createSingleLoginLayer();
  loginLayer.style.display = "none"
}
// 改變iframe的src屬性
document.getElementById("changeUrlBtn").onclick = function(){
  var loginLayer = createSingleIfame();
  loginLayer.src = "http://127.0.0.1:5500/index.html";
}
相關文章
相關標籤/搜索