理解设计模式之单例模式(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

复制代码
相关文章
相关标签/搜索