如何确保一个类只有一个实例?单例模式大解析
前言
单例模式是我们前端开发中最常用的设计模式,它确保了一个类只有一个实例。这一特性在我们的应用中发挥了极大的作用,特别是我们需要对某一资源进行共享或者是我们需要频繁实例化某个对象但是又要确保其只有一个实例化对象。
什么是单例模式
单例模式是一种广泛使用的软件设计模式,其核心思想是确保一个类在整个应用运行期间只有一个实例,并提供一个全局访问点来获取这个实例。这样的设计模式有助于控制共享资源的访问,减少系统开销,同时可以简化对全局状态的管理。
如何实现单例模式
单例模式有多种实现方法,而我们最常用的实现方法就是懒汉式
实现思想
我们实例化一个对象都是直接new一个对象,但是每new一个就会创建一个新的实例化对象,所以我们要实现单例模式,就不能直接new它。我们通过一个方法将实例对象返回出去,我们只需要调用该方法就能创建一个实例对象,如果已经创建过了,那么直接返回创建过的对象,如果没有那就新创建一个对象。
懒汉式
懒汉式的特点是在第一次需要使用实例时才去创建它,即惰性初始化,这样实现了延迟加载,节省了资源。
class Singleton {
constructor() {
// 在这里初始化单例实例
this.instance = null;
}
static getInstance() {
if (!this.instance) {
this.instance = new Singleton();
}
return this.instance;
}
}
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
}
此时我们实例化的两个对象s1,s2就是同一个实例对象
饿汉式
饿汉式的特点就是在类或对象被加载时立即创建实例,就不是在要使用它的时候再创建。这样在保证了线程的安全,但是这样做会造成资源的浪费。虽然js是单线程的,但是这一点在js中不构成问题
const Singleton = (function () {
// 在这里初始化单例实例
const instance = new Object();
return {
getInstance: function () {
return instance;
},
};
})();
// 使用
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2);
单例模式的优缺点
优点:
- 控制了实例的唯一性,减少了系统开销。
- 提供了对唯一实例的全局访问点。
缺点:
- 违反了单一职责原则,单例类既负责创建实例也负责提供业务功能。
- 不易于测试,尤其是当单例持有外部资源时。
- 难以实现序列化与反序列化保持单例的状态。
- 在多线程环境中,实现线程安全需要额外的处理。
实战演示
我们在处理浏览器localStorage时,不需要创建多个实例,因为它是基于浏览器窗口的一个全局存储空间。通过单例模式确保整个应用中只有一个 Storage
实例,可以避免不必要的内存占用和资源浪费。我们在下面这段代码通过JavaScript的类和单例模式来封装和管理浏览器的localStorage
操作
class Storage {
// static instance;
static getInstance() {
// JS 动态 static 属性
// JS 没有类,都是对象
if (!Storage.instance) {
Storage.instance = new Storage();
}
return Storage.instance;
}
getItem(key) {
return localStorage.getItem(key);
}
setItem(key, value) {
localStorage.setItem(key, value);
}
}
export default Storage
我们接下来就可以使用使用Storage
的单例来设置和获取数据了,由于采用了单例模式,无论你在应用的哪个部分调用Storage.getInstance()
,返回的都是同一个实例,所以可以放心地在应用的多个位置使用它,而不用担心实例不一致的问题。
总结
单例模式因其简单实用,在实际开发中有着广泛的应用。然而,正如所有设计模式一样,它也有适用场景和局限性。所以我们要合理选择,以达到最好的效果。
转载自:https://juejin.cn/post/7388091090321621018