转载

单例模式

const Singleton = function(name){
 this.name = name
 this.instance = null
}
Singleton.getInstance = function(name){
 if (!this.instance) {
 this.instance = new Singleton(name)
 }
 return this.instance
}
const a = Singleton.getInstance('mertens')

这个例子我们可以通过 Singleton.getInstance 来获取 Singleton 类的唯一对象,但有一个问题是这样增加了这个类的不透明性, Singleton 类的使用者必须知道这是一个单例类,并且跟以往通过 new XXX 的方式来获取对象不一样,这里需要用 Singleton.getInstance 来获取对象

透明的单例模式

const CreateDiv = (function(){
 let instance
 const CreateDiv = function(html){
 if (instance) {
 return instance
 }
 this.html = html
 this.init()
 return instance = this
 }
})()

虽然上面的代码完成了一个透明的单例类的编写,但是它同样有一些缺点。

这段代码中, CreateDiv 的构造函数实际上做了两件事情

  1. 创建对象和执行初始化 init 方法
  2. 保证只有一个对象

假设哪天我们需要利用这个类,把它变成一个普通的可以变成可以产生多个实例的类,我们就需要重写这个类。

用代理实现单例

现在我们通过引入代理类,来解决上面那个问题。

const CreateDiv = function(html){
 this.html = html
 this.init()
}
const ProxySingletonCreateDiv = (function(){
 var instance
 return function(html){
 if (!instance) {
 instance = new CreateDiv(html)
 }
 return instance
 }
})()

通用的惰性单例

我们需要创建页面中唯一的 iframe ,或者 script 标签

const createIframe = (function(){
 const iframe
 return function(){
 if (!iframe) {
 iframe = document.createIframe('iframe')
 iframe.style.display = 'none'
 document.body.appendChild(iframe)
 }
 return iframe
 }
})()

上面是创建一个 iframe,如果是创建一个 script 标签,套路也是差不多的

const obj
if (!obj) {
 obj = xxx
}

现在我们可以把通用的逻辑抽象出来

const getSingle = function(fn){
 let result
 return function(){
 return result || result = fn.apply(this, arguments)
 }
}

const createLoginLayer = function(){
 const div = document.createElement('div')
 div.innerHTML = '我是登录浮窗'
 div.style.display = 'none'
 document.appendChild(div)
 return div
}

const createSingleLoginLayer = getSingle(createLoginLayer)
// 接下来,我们可以继续创建一个 iframe

const createSingleIframe = function(){
 const iframe = document.createElement('iframe')
 document.body.appendChild(iframe)
 return iframe
}

document.getElementById('loginBtn').onClick = () => {
 const LoginLayer = createSingleIframe()
 LoginLayer.src = 'http://www.xxx.com'
}

在这个例子中,我们把创建实例对象的职责和管理单例的职责分别放置在两个方法里面,这两个方法可以独立变化而不影响,当他们连接在一起的时候,就完成了创建唯一实例对象的功能。

原文  http://mertensming.github.io/2017/01/23/js-singleton/
正文到此结束
Loading...