「回顾2022,展望2023,我正在参与2022年终总结征文大赛活动」
前言
单例模式相信大家都有所听闻,甚至也写过不少了。在面试中也是考得最多的其中一个设计模式,本文也是刚学了一点javascript的单例模式的体会,希望对大家能够有所帮助~~~
什么是单例模式
单例模式是指在内存中只会创建且仅创建一次对象的设计模式。 在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。
在JavaScript中,通俗来讲就是 保证一个类,仅有一个实例
单例模式的类型
单例模式有两种类型:
- 懒汉式:在真正需要使用对象时才去创建该单例类对象
- 饿汉式:在类加载时已经创建好该单例对象,等待被程序使用
这里,我们主要针对于懒汉式类型展开来聊一聊吧~
模式特点
- 类只有一个实例
- 全局可访问
- 推迟初始化(与静态类,对象的区别)
- 主动实例化
应用场景
- 登录弹窗
- 购物车
- 命名空间
- 引入第三方库(多次引用只会使用一个库引用,如jQuery)
- 全局态管理store-Vuex
懒汉式创建单例对象
核心方法大概就是:创建对象的方法是在程序使用对象前,先判断该对象是否已经实例化 (判空), 若已实例化直接返回该类对象。,否则就先执行实例化操作。
简单版单例模式
// 写法一
class Person {
say() {
console.log('百宝箱');
}
static getInstance() {
if (!Person.instance) {
Person.instance = new Person();
}
return Person.instance
}
}
const p1 = Person.getInstance()
const p2 = Person.getInstance()
console.log(p1 === p2); // 执行结果为 true
让这个类永远只能创建出一个实例对象,这个就是单例模式
// 闭包的写法
class Person {
say() {
console.log('百宝箱');
}
}
Person.getInstance = (function () {
let instance = null
return function () {
if (!instance) {
instance = new Person()
}
return instance
}
})()
const p1 = Person.getInstance()
const p2 = Person.getInstance()
console.log(p1 === p2); // 执行结果为 true
以上就是懒汉式创建单例对象的方法。这里我们其实也可以联想到,vuex的使用也是单例模式,vuex的使用是为了实现全局的store,创建store的方式是把单例模式的思想得以应用。
“惰性”单例模式
需要时才创建实例对象,按需加载。
需求:页面弹窗提示。多次调用,都只有一个弹窗对象,内部html不同
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单例模式的弹框</title>
<style>
#model {
width: 200px;
height: 200px;
line-height: 200px;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border: 1px solid #000;
text-align: center;
}
</style>
</head>
<body>
<button id="open">打开弹框</button>
<button id="close">关闭弹框</button>
<script>
const Model = (function () {
let model = null
return function () {
if (!model) {
model = document.createElement('div')
model.innerHTML = '全局唯一的model'
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();
if (model) {
model.style.display = 'none';
}
})
</script>
</body>
</html>
优缺点
- 优点:适用于单一对象,只生成一个对象实例,避免频繁创建和销毁实例,减少内存占用
- 缺点:不适用动态扩展对象,或需创建多个相似对象的场景