代码优雅之道——聊聊单例模式
前言
单例模式是一种设计模式,确保类只有一个实例,并提供全局访问点。在 JavaScript 中,可以通过立即执行函数和闭包来创建单例,从而避免多次实例化和资源浪费。通过单例模式,可以方便地管理全局状态和共享资源,提高代码的可维护性和可扩展性。
话题引入
我们首先看这段代码,我们知道两者肯定不会相等,那么有没有一种方法,让我们可以创建两个完全一样的对象呢?
方法一
我们定义一个静态方法,如果没有创建实例(构造函数的属性不存在)我们就创建一个实例,并且作为构造函数的属性,已经存在我们就直接返回这个属性。
方法二
我们还可以使用闭包,具体操作是设置了一个只有构造函数本身可以访问的方法,我们通过闭包的方式返回出一个函数体,函数体内返回值。
这样子的话,我们就会发现两者是完全一样的啦!
单例模式应用一
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="save">存储</button>
<button id="get">取值</button>
<script>
let save = document.getElementById('save')
let get = document.getElementById('get')
class Storage {
static getInstance() {
if (!Storage.instance) {
Storage.instance = new Storage()
}
return Storage.instance
}
getItem(key) {
return localStorage.getItem(key)
}
setItem(key, val) {
return localStorage.setItem(key, val)
}
}
const storage = Storage.getInstance()
const storage2 = Storage.getInstance()
save.onclick = function () {
// localStorage.setItem('name', '高老师')
storage.setItem('name', '高老师')
}
get.onclick = function () {
alert(storage2.getItem('name'))
}
</script>
</body>
</html>
比如如果要我们去手写本地存储。要想让Storage达到和localStorage一样的效果,我们采用的是非闭包方法,我们这个时候的两个storage对象是一样的,因此我们可以实现正常的赋值取值。这个时候就实现了和之前一样的效果。
单例模式应用二
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
text-align: center;
}
#model {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border: 1px solid #000;
line-height: 200px;
display: none;
}
</style>
</head>
<body>
<button id="open">打开弹框</button>
<button id="close">关闭弹框</button>
<!-- <div id="model">
我是弹出框
</div> -->
<script>
const Model = (function () {
let model = null
return function () {
if (!model) {
model = document.createElement('div')
model.innerHTML = '我是全局唯一的弹框'
model.id = 'model'
model.style.display = 'none';
document.body.appendChild(model)
}
return model
}
})()
document.getElementById("open").addEventListener("click", () => {
const model = new Model()
model.style.display = 'block'
});
document.getElementById("close").addEventListener("click", () => {
const model = new Model()
model.style.display = 'none'
});
</script>
</body>
</html>
首先我们要知道如果全文需要多个相同的弹框,我们不必设置每一个,只需要设置一个。大家用的时候直接调用就可以,这里我们采用了闭包的方式,model就是一个自执行函数的结果,最后返回model,因此我们最终调用的model都是同一个。
小结
在 JavaScript 中,单例模式用于确保一个类只有一个实例,并提供一个全局访问点。通常使用闭包来实现单例模式,通过立即执行函数和私有变量来封装实例化过程,从而避免多次创建实例和资源浪费。单例模式能够有效地管理全局状态和共享资源,提高代码的可维护性和可扩展性。它常用于创建唯一的对象,例如应用程序的配置信息、日志记录器、缓存等。同时,单例模式还可以结合惰性单例模式,延迟实例化过程,直到真正需要时才进行实例化。在现代 JavaScript 中,单例模式可以与模块化开发相结合,通过模块化方案(如ES6 模块)来管理单例对象。因此,了解单例模式的概念和实现方式对于构建高效、可维护的 JavaScript 应用程序是非常重要的。
转载自:https://juejin.cn/post/7377298855228260387