前端开发设计模式:单例模式之场景应用&实现
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。
常见场景
1、全局状态管理
在前端应用中,常需要管理全局状态,像用户登录信息,主体设置等。借助单例模式,能保证全局状态的唯一性和一致性。
例:在vue.js 项目中,使用单例模式创建一个全局状态管理对象
// state.js // GlobalState 类用于管理全局状态,它通过保存用户和主题信息来维护应用的状态 class GlobalState { // 构造函数确保只有一个实例被创建,它初始化用户和主题状态 constructor() { if (!GlobalState.instance) { this.user = null; // 初始用户状态为 null this.theme = "light"; // 初始主题为 light GlobalState.instance = this; // 保存实例 } return GlobalState.instance; // 返回实例,防止新实例创建 } setUser(user) { this.user = user; } setTheme(theme) { this.theme = theme; } } const globalState = new GlobalState(); Object.freeze(globalState); // 冻结实例以防止修改,确保状态管理的完整性 export default globalState;
// someone.vue
// 在组件中使用 import globalState from './state.js'; export default { created(){ globalState.setUser({name:'John Doe'}) globalState.setTheme('dark') } }
解释:
- GlobalState 类确保只有一个实例存在,在整个应用中,任何组件都可以通过引入 globalState 来访问和修改全局状态
 - Object.freeze() 是JS中的一个内置方法,用于冻结一个对象。所谓 “冻结”,意味着该对象的状态被固定,不能再对其进行修改,具体包括不能添加新属性、不能删除已有属性、不能修改属性的可枚举性、可配置性、可写性,以及不能修改属性的值。
 
2、日志记录器
使用单例模式创建日志记录器,能保证所有日志信息都被集中处理。
例:创建一个单例日志记录器。
// logger.js class Logger { constructor() { if (!Logger.instance) { this.logs = []; Logger.instance = this; } return Logger.instance; } // 记录一条日志信息 log(message) { this.logs.push(message); } } const logger = new Logger(); Object.freeze(logger); export default logger;
// someone.vue 在组件中使用 import logger from "./logger.js"; export default { created() { logger.log("component created"); }, };
解释:Logger 类的实例是唯一的,在应用的任何地方调用 logger.log 方法,日志信息都会被记录到同一个数组中,方便后续查看和分析。
3、弹窗管理
使用单例模式管理弹窗,可以避免同时出现多个相同类型的弹窗。
例:创建一个单例弹窗管理器。
// modalManager.js
class ModalManager { constructor() { if (!ModalManager.instance) { this.modal = null; ModalManager.instance = this; } return ModalManager.instance; } openModal(modal) { if (!this.modal) { this.modal = modal; // 打开弹框的逻辑 } } closeModal() { if (this.modal) { // 关闭弹框的逻辑 this.modal = null; } } } const modalManager = new ModalManager(); Object.freeze(modalManager); export default modalManager;
//someone.vue 在组件中使用 import modalManager from "./modalManager.js"; export default { methods: { showModal() { modalManager.openModal("confirm Modal"); }, hideModal() { modalManager.closeModal(); } } };
解释:ModalManager 类确保只有一个弹窗实例被管理。 在调用 openModal 方法,只有当当前没有打开的弹窗时才会打开新的弹窗,避免弹窗重叠的问题。
4、数据库连接
前端使用 indexDB 等数据库时,为避免创建多个数据库连接导致资源浪费和冲突,可使用单例模式来管理数据库连接。
例:创建一个单例的 indexDB 连接管理
// dbConnection.js class DBConnection { constructor() { if (!DBConnection.instance) { this.db = null; this.initDB(); DBConnection.instance = this; } return DBConnection.instance; } // 初始化数据库连接 async initDB() { // 使用 indexedDB 创建一个名为 'myDB' 的数据库 const request = indexedDB.open("myDB", 1); request.onsuccess = (event) => { this.db = event.target.result; }; request.onerror = (event) => { console.error("Error opening database:", event.target.error); }; } getDB() { return this.db; } } const dbConnection = new DBConnection(); Object.freeze(dbConnection); export default dbConnection;
// someone.vue 在组件中使用 import dbConnection from './dbConnection.js' export default { async created(){ const db = dbConnection.getDB() if(db){ // 进行数据库操作 } } }
解释:在需要使用数据库时,通过 dbConnection.getDB() 方法获取连接,避免重复创建连接
5、缓存管理
在前端开发中,为了提高性能,常会使用缓存来存储一些经常使用的数据。使用单例模式管理缓存,可以确保缓存的一致性和高效性。
例:创建一个单例缓存管理器
// cacheManager.js class CacheManager { constructor() { if (!CacheManager.instance) { this.cache = {}; CacheManager.instance = this; } return CacheManager.instance; } set(key, value) { this.cache[key] = value; } get(key) { return this.cache[key]; } remove(key) { delete this.cache[key]; } } const cacheManager = new CacheManager(); Object.freeze(cacheManager); export default cacheManager;
// someone.vue 在组件中使用 import cacheManager from "./cacheManager.js"; export default { created() { cacheManager.set("data", { name: "John" }); const data = cacheManager.get("data"); console.log(data); }, };
解释:CacheManager 类的实例是唯一的,在应用的任何地方都可以通过 cacheManager 来设置、获取和删除缓存数据,保存了缓存数据的一致性和高效管理。
                    
                
                
            
        
浙公网安备 33010602011771号