什么是单例模式?
1.只有一个实例
2.可以全局访问
它解决了什么问题?
一个全局使用的类被频繁的创建和销毁。
什么时候使用单例模式?
需要控制实例的数目,节省系统化资源的时候。
如何实现单例模式?
判断系统中是否已经有这个单例,有则返回,无则创建。
单例模式的优点:
内存中只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如首页页面的缓存)
使用场景:
1.全局的缓存
2.弹窗
es5实现单例模式
比如做一个登录弹窗,一般思路是这样的:先将登录框写好,加入到body中,并把它隐藏,当点击登录按钮时将登录框显示出来。
<button id="btn">登录</button>
<script>
var loginLayer=(function(){
var div=document.createElement('div')
div.innerHTML='登录弹窗'
div.style.display='none'
document.body.appendChild(div)
return div
})()
document.getElementById('btn').onclick=function(){
loginLayer.style.display='block'
}
</script>
这样做的缺点:造成了资源的浪费。因为不管有没有点击登录按钮,登录框都被加入到了body中,只是设置了隐藏属性而已。
当然,我们可以将生成登录框的代码写到onclick事件里边,点击登录按钮时才创建。然而这样做,当多次点击按钮时,会生成多个登录框,也即频繁的创建和销毁。
我们需要先判断一下实例是否存在,不存在才创建,这样就解决了上边的问题,这就是单例模式。
var createLoginLayer = function () {
var div
return function () {
if (!div) {
div = document.createElement('div')
div.innerHTML = '登录弹窗'
div.style.display = 'none'
document.body.appendChild(div)
}
return div
}
}
document.getElementById('btn').onclick = function () {
var loginLayer=createLoginLayer()
loginLayer().style.display = 'block'
}
进一步改进:
单一职责,对于类似的功能,我们可以将代码进行抽离,实现代码的复用。
// 单一职责
// 单例职责
var getSingle = function (fn) {
var result
// 短路
return function () {
return result || (result = fn(this, arguments))
}
}
// 创建登录框职责
var createLoginLayer = function () {
var div = document.createElement('div')
div.innerHTML = '登录弹窗'
div.style.display = 'none'
document.body.appendChild(div)
return div
}
var createLogin=getSingle(createLoginLayer)
document.getElementById('btn').onclick = function () {
var loginLayer=createLogin() // div
loginLayer.style.display = 'block'
}