模式概念
单例模式(Singleton Pattern)是一种对象创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。
它的核心思想是:
- 唯一性:保证一个类只有一个实例。
- 全局访问点:提供一种方式来获取这个唯一的实例。
通常用于管理共享资源,如配置信息、线程池、缓存等。
模式结构
- Singleton(单例类) :包含一个私有静态变量来持有类的唯一实例,并提供一个公有静态方法来获取这个实例。
代码实现
class Singleton {
static instance = null;
constructor() {
// 私有构造函数
}
static getInstance() {
if (!Singleton.instance) {
// 确保只创建一个实例
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
doSomething() {
console.log("Doing something...");
}
}
// 获取单例对象并调用方法
const singleton = Singleton.getInstance();
singleton.doSomething();
// 再次获取单例对象,将得到同一个实例
const anotherInstance = Singleton.getInstance();
console.log(singleton === anotherInstance); // 输出 true
- 通过
Singleton.getInstance()方法,无论何时调用,都将返回同一个实例。 - 单例对象的创建是延迟的,即在第一次调用
getInstance()方法时才创建。
也可以使用闭包来实现
const Singleton = (function () {
let instance;
function init() {
// 私有变量和方法
const privateMethod = function () {
console.log("Private method");
};
return {
publicMethod: function () {
console.log("Public method");
privateMethod();
},
// 可以在这里添加更多公开方法
};
}
return {
getInstance: function () {
if (!instance) {
instance = init();
}
return instance;
},
};
})();
// 获取单例对象并调用方法
const singleton = Singleton.getInstance();
singleton.publicMethod();
// // 再次获取单例对象,将得到同一个实例
const anotherInstance = Singleton.getInstance();
console.log(singleton === anotherInstance); // 输出 true
模式效果
模式的优点:
- 资源节约:由于只有一个实例,因此可以节约系统资源。没有频繁的创建和销毁,占用内存的行为。
- 一致性:确保系统中的数据一致性。
- 控制全局访问:可以控制实例的访问方式。
模式的缺点:
- 全局状态:单例类的职责过重,持有的全局状态可能导致代码难以测试和维护。
- 扩展性:单例模式本身是解决扩展性问题的一种方式,一定程度上违背了
单职责原则,过度使用可能导致代码难以扩展。 - 多线程环境:在多线程环境中需要额外的处理来保证线程安全。(虽然在 JavaScript 的单线程环境中不常见)
在以下情况下可以使用单例模式:
- 系统只需要一个实例对象,或者因为资源消耗太大而只允许创建一个对象。
- 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该示例。
模式应用
在一些现有的 JavaScript 库中,单例模式也被广泛应用。例如:
jQuery
jQuery 库本身并不是一个典型的单例模式实现,但它的一些特性使得它在实际使用中表现为单例模式。这种模式使得 jQuery 在处理 DOM、事件和其他浏览器 API 时非常方便和强大。
特征:
- 全局访问点:jQuery 通过
$符号或jQuery方法提供了一个全局访问点,这使得你可以在任何地方访问 jQuery 实例。 - 唯一实例:尽管你可以多次调用
jQuery()或$(),它们都会返回相同的 jQuery 对象实例。
// 初始化 jQuery 对象
const myjQueryObject = jQuery("<div>Hi, I'm a jQuery object!</div>");
// 另一种方式,使用 $ 作为别名
const myjQueryObject = $("<div>Hi, I'm a jQuery object!</div>");
// 访问全局 jQuery 对象
console.log(jQuery); // 输出 jQuery 对象
console.log($); // 输出 jQuery 对象
Pinia
Pinia 是 Vue 3 的官方状态管理库,它被设计为 Vuex 的替代品。Pinia 的核心是围绕单个 Store 实例构建的,这个 Store 实例在整个应用程序中是唯一的,这体现了单例模式的一些关键特征。
特征:
- 单个 Store 实例:在 Pinia 中,使用
defineStore创建的每个 Store 都是一个单例。这意味着无论何时创建一个 Store 实例,都会返回相同的实例。 - 全局状态访问:Pinia 提供了一个全局的
useStore钩子,允许你在应用程序的任何组件中访问 Store 实例。 - 集中状态管理:由于 Store 实例是单例的,Pinia 可以集中管理应用程序的状态。
//定义 Store
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
//使用store
<script setup>
import { useCounterStore } from '@/stores/counter'
// 可以在组件中的任意位置访问 `store` 变量 ✨
const store = useCounterStore()
</script>
今天的分享就到这里,希望可以帮助到你!假如你对文章感兴趣,可以来我的公众号:小新学研社。