理解設計模式之單例模式(Javascript)

單例模式

單例就是確保一個類只有一個實例,任什麼時候候調用的實例都是同一個,這個實例只會初始化一次。緩存


方式一

實現步驟:

  1. 最簡單的——對象字面量的方式

其字面量裏能夠包含大量的屬性和方法,直接建立好的單例對象。這樣建立的對象變量全局化了,閉包

var instance={
    prop1: "prop1",
    prop2: "prop2",
    method1: function () {
        console.log('hello world');
    }
}
複製代碼
  1. 擴展該單例對象能夠添加本身的私有變量和方法,只暴露公有變量和方法方式,經過閉包的方式來實現。
var mySingleton = function(){

// 私有變量和方法
    var priv_prop='private prop';
    var priv_mtd = function(){
        console.log(priv_prop)
    }
    
// 公有變量和方法,能訪問私有變量和方法
    return {
        pub_mtd: function(){
            priv_mtd()
        },
        pub_prop: 'public prop'
    }
}

var instance = mySingleton();
instance.pub_mtd();  // 輸出 'private prop'
console.log(instance.pub_prop);  // 輸出 'public prop'
複製代碼

事實上這裏的mySingleton()並非單例的,只是在第一步上作了擴展能夠訪問私有變量函數

var instance2 = mySingleton();
instance === instance2  //false
複製代碼
  1. 真正的建立實例,每次調用的都是同一個對象實例,第一調用纔會初始化。
var Singleton = (function(){
    // 這裏定義單例代碼
    var instance;
    function init(){
        return {
            pub_mtd: function(){
                console.log('this is pub_mtd');
            },
            pub_prop:'this is pub_prop'
        }
    };
    
    return {
        getInstance:function(){
            if (!instance){
                instance = init()
            }
            return instance
        }
    }
})()
/*調用公有的方法的時候初始化實例:*/
Singleton.getInstance().pub_mtd();

let a=Singleton.getInstance();
let b=Singleton.getInstance();
a === b // true 此時纔算是真正的單例
a.pub_mtd === b.pub_mtd //true
a.pub_mtd() //打印出'this is pub_mtd';
複製代碼

此時纔算是真正的單例,任什麼時候候調用Singleton.getInstance()都是同一個實例。ui


其餘實現方式

方法1-經過重寫構造函數直接調用前一次生成的實例

function Instance(){
    var instance = this;
    
    console.log(111)
    
    this.prop='prop';
    this.mtd=function(){
        console.log(this.prop);
    }
    
    //重寫構造函數
    Instance = function(){
        console.log(222)
        return instance;
    }
}

var a = new Instance()  // 打印出111,同時構造函數被重寫,
var b = new Instance()  // 打印出222,直接返回前一次調用緩存的instance
a === b // true
複製代碼

方法2-把首次生成的實例緩存到構造函數的屬性上

function Instance(){
    if (typeof Instance.instance === 'object'){
        return Instance.instance
    }
    
    this.prop='prop';
    this.mtd=function(){
        console.log(this.prop);
    };
    
    // 緩存
    Instance.instance=this;
    // 隱式返回 this
}

var ins1=new Instance();
var ins2=new Instance();
ins1 === ins2
複製代碼

方法3-內部重寫構造函數,修改原型屬性,重設構造函數指針

function Instance(){
    var instance;
    console.log(1)
    // 二次調用的構造函數
    Instance = function Instance(){
        console.log(2)
        return instance;
    };
    console.log(3)
    // 後期處理原型屬性
    Instance.prototype = this;
    
    // 實例
    instance = new Instance();
    console.log(4)

    // 重設構造函數指針
    instance.constructor = Instance;
    
    instance.prop='prop';
    instance.mtd=function(){
        console.log(instance.prop)
    }
    console.log(5)
    return instance
}
var a = new Instance();
// 13245
var b = new Instance();
// 2

複製代碼
相關文章
相關標籤/搜索