javascript设计模式 - 单例模式
mhahaha opened this issue · 0 comments
mhahaha commented
单例模式定义: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
适用场景:全局只需要一个的对象时,例如线程池,全局缓存等
实现一个标准的单例模式
原理:获取一个实例时先判断该实例是否创建,若未创建,则先创建并缓存,然后返回实例;若已创建,则返回缓存中的实例。
示例代码:
const userInfo = null
const getUserInfo = (name, info) => {
if (!userInfo) {
userInfo = {
name: name,
info: info
}
}
return userInfo
}当使用这种方式创建一个仅有的实例时,我们是在全局作用域中新增全局变量,存在很多全局变量时,很容易造成变量污染,所以我们要么适当使用命名空间来控制全局变量数量,例如:
const userInfo = null
const namespace1 = {
a: 1,
b: 2
}要么使用闭包来封装私有变量,仅暴露跟外界通信的接口:
const user = (() => {
const name = 'dev'
const age = 20
return {
getUserInfo: () => {
return `${name} - ${age}`
}
}
})()惰性单例
惰性单例在我们实际开发过程是很常用也很重要的技术,例如我们页面初始化时创建登录弹窗,我们常见的做法可能有以下几种:
1.静态直出直接添加弹窗,控制其显示及隐藏
2.需要登录时初始化,退出时remove
3.需要登录时初始化,退出时hide
可以比较三者的消耗,第三种显然是最合理的,我们进入一个页面只是想看一些附加功能,可能并不需要登录,也可能我们登录之后需要退出登录进行账号的切换...
惰性单例的核心就是对象被调用时才会被真正创建。
通用惰性单例
开发过程中,我们发现有一段代码可以复用时,我们当然是想直接copy过来,但此时如果让我们去熟悉里面的逻辑并做部分修改,我个人是比较排斥的。同样的道理,写单例模式时,我们也要尽量做到其通用性。
通用惰性单例 = 改变的业务逻辑 + 不变的单例模式框架
const getSingleton = fn => {
let result
return () => {
return result || (result = fn.apply(this, argument))
}
}此时,任何业务都可以以参数的形式进行传递来完成一次单例模式的使用,例如:
const createLoginIframe = () => {
const iframe = document.createElement('iframe')
document.body.appendChild(iframe)
return iframe
}
const loginIframe = getSingleton(createLoginIframe)在这个例子中可以看出,职责比较分明,创建实例对象的职责和管理单例的职责放置在两个方法里面,没有业务耦合,完成了单例模式的通用性。