1

1. 介绍

单例模式是JS设计模式中一种常用的模式

2. 定义

保证一个类中仅有一个实例,且提供一个访问它的全局访问点

3. 应用

一些只需要出现的一个UI组件,如登录窗口、弹窗toast、遮罩mask

4. 思想

用一个变量来标记是否已创建过对象,如果是就返回已创建过对象,如果不是则创建对象

5. 实现

1.基本的单例模式

 var Singleton=function(){
        this.instance=null
    }
    Singleton.getInstance=(function(){
        var instance=null
        return function(){
            if(!instance){
                instance=new Singleton()
            }
            return instance
        }
    })()
    Singleton.getInstance()

这就是一个基本的单例模式,但是这个单例模式看起来有些怪异,要求使用者必须知道Singleton类是一个单例类,不透明。获取对象一般是new XXX实现而这里是需要调用Singlenton的静态函数getInstance,。

2. 透明单例模式

我们要对上面的例子进行改造优化使得变得透明,和其他获取对象的方式一样,使用new XXX的格式,下面大致实现了一下,例子中还有很多的不足,主要是提供使用new方式的一种思路。

var Singleton=(function(){
    var instance=null
    var createDiv=function(){
        if(instance){
           return instance
        }
        instance=document.createElement("div")
        instance.innerHTML="div"
    }
    return function(){
        return instance||(instance=createDiv.apply(this))
    }
})()
var a = new Singleton()
var b=new Singleton()
console.log(a===b)//true

3. 用代理实现单例模式

例子2虽然初步实现了我们要的功能,但是在实际情况中,创建一个对象的情况可能复杂得多,例如传参,给元素设定颜色,设定文字等,而createDiv函数就会变得臃肿,而且如果有一希望可能返回多个对象就需要对createDiv进行改造
可以通过代理来实现,类负责具体的实现,单例决定要不要创建实例

var Singleton=function(){
    this.createDiv()
}
Singleton.prototype.createDiv=function(){
   this.instance= document.createElement("div")
}
var ProxySinglenton=(function(){
    var instance
    return function(){
        if(!instance){
            instance=new Singleton()
        }
    return instance
    }
})()
var a = new ProxySinglenton()
var b = new ProxySinglenton()
console.log(a===b)//true

不过个人觉得为了使用单例而去创建一个代理类有些浪费

4. 使用全局变量

上面三种方式都是去模仿传统的面向对象语言去创造单例的,先定义类,再从类中去创造单例,但js本身是没有类的,可以不用定义类。从单例的定义来说,全局变量也是单例,可以使用全部变量来创建单例,例如 var a={},但这种方式容易造成命名污染

5. 惰性单例

惰性单例的意思是需要的时候才创建对象
惰性单例的实现可以结合全局变量,因为前面说过既然是单例没有必要去定义一个类。这个例子中把创建对象和管理单例分开,创建对象的函数作为参数传入管理单例函数中,实现不同单例的创建。这也是通用的惰性单例。

var getSingle=function(fn){
    var result
    return function(){
        return result||(result=fn.apply(this))
    }
}
var createSingleDiv=function(){
    var div=document.createElement("div")
    return div
}
var createP=function(){
    var p =document.createElement("p")
    return p
}
var createSingleDiv=getSingle(createDiv)
var createSingleP=getSingle(createP)

6. 建议

这里的例子中虽然大有不同,但是都有一个共同点是利用了闭包的特性,延长判断是否创建单例的变量的生命周期,对闭包有一定了了解更能体会到其中的妙处。


LJun
60 声望2 粉丝