JS常用设计模式汇总

1、基于类的单例模式

// PageManager.js
class PageManager {constructor(config) {if (!PageManager.instance) {this.config = config;this.initialized = false;PageManager.instance = this;this.init();}return PageManager.instance;}init() {if (this.initialized) return;console.log('Initializing with config:', this.config);// 实际初始化逻辑this.initialized = true;}generatePage(instruction) {if (!this.initialized) {throw new Error('PageManager not initialized');}const page = {...this.config,...instruction,id: Date.now()};console.log('Generated page:', page);return page;}// 更新配置(新增方法)updateConfig(newConfig) {Object.assign(this.config, newConfig);}// 获取实例的静态方法(推荐方式)static getInstance(config) {if (!PageManager.instance) {PageManager.instance = new PageManager(config);}return PageManager.instance;}
}// 不立即初始化,而是导出类
export default PageManager;

使用方式

// 使用方可以决定何时初始化
import PageManager from './PageManager';// 第一次获取实例时初始化(推荐方式)
const pageManager = PageManager.getInstance({defaultTemplate: 'advanced',baseStyles: true
});// 生成页面
const homePage = pageManager.generatePage({ title: 'Home', content: 'Welcome' 
});// 后续获取仍然是同一个实例
const sameManager = PageManager.getInstance();
console.log(pageManager === sameManager); // true// 可以更新配置
pageManager.updateConfig({defaultTemplate: 'custom'
});

2、更优雅的变体:模块模式单例

如果你更喜欢模块模式而不是类,这里有一个更符合JavaScript习惯的实现:

// pageManager.js
let instance = null;
let config = {};
let initialized = false;const init = (initialConfig) => {if (initialized) {console.warn('PageManager already initialized');return;}config = {defaultTemplate: 'standard',...initialConfig};initialized = true;console.log('PageManager initialized with config:', config);
};const generatePage = (instruction) => {if (!initialized) throw new Error('PageManager not initialized');return {...config,...instruction,id: `page-${Date.now()}`};
};const updateConfig = (newConfig) => {Object.assign(config, newConfig);
};// 导出单例对象
export default {init,generatePage,updateConfig
};

使用方式:

import pageManager from './pageManager';// 在使用前初始化
pageManager.init({defaultTemplate: 'custom'
});// 使用单例
const page = pageManager.generatePage({ title: 'About' });

3、使用工厂函数(更灵活)

// 使用示例
// createPageGenerator.js
export const createPageGenerator = (initialConfig) => {const config = {defaultTemplate: 'standard',basePath: '/',...initialConfig};const generate = (instruction) => {const pageId = `${config.basePath}${instruction.slug || `page-${Date.now()}`}`;return {...config,...instruction,id: pageId,fullPath: `${config.basePath}${instruction.path || ''}`,createdAt: new Date()};};const updateConfig = (newConfig) => {Object.assign(config, newConfig);};return {generate,updateConfig,getConfig: () => ({ ...config })};
};// 使用示例
// 可以创建多个实例或单个实例使用

基本使用

// 使用示例
import { createPageGenerator } from './createPageGenerator';// 1. 创建实例(简单配置)
const simpleGenerator = createPageGenerator();
const page1 = simpleGenerator.generate({ title: 'Home' });
console.log(page1);

4、发布-订阅模式 (Pub-Sub Pattern)

用途:观察者模式的变体,使用主题/通道概念解耦发布者和订阅者。

class EventBus {constructor() {this.events = {};}subscribe(eventName, callback) {if (!this.events[eventName]) {this.events[eventName] = [];}this.events[eventName].push(callback);}publish(eventName, data) {if (this.events[eventName]) {this.events[eventName].forEach(callback => callback(data));}}unsubscribe(eventName, callback) {if (this.events[eventName]) {this.events[eventName] = this.events[eventName].filter(cb => cb !== callback);}}
}// 使用
const bus = new EventBus();// 订阅
const logData = data => console.log('Received:', data);
bus.subscribe('dataUpdate', logData);// 发布
bus.publish('dataUpdate', { newData: 123 });// 取消订阅
bus.unsubscribe('dataUpdate', logData);// 实际应用:Vue的EventBus、组件间通信

5、观察者模式 (Observer Pattern)

// 主题(被观察者)
class Subject {constructor() {this.observers = [];}subscribe(observer) {this.observers.push(observer);}unsubscribe(observer) {this.observers = this.observers.filter(obs => obs !== observer);}notify(data) {this.observers.forEach(observer => observer.update(data));}
}// 观察者
class Observer {update(data) {console.log('Observer received:', data);}
}// 使用
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();subject.subscribe(observer1);
subject.subscribe(observer2);subject.notify('Hello observers!'); // 两个观察者都会收到通知// 实际应用:事件系统、状态管理(如Redux)、数据绑定

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/84668.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/84668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

迈向软件开发 T 型人才之路:构建多元能力体系

在软件开发的广袤天地里,T 型人才备受瞩目。这类人才犹如具备强大能量的 “多面手”,既有深入专精的技术能力,又有广泛多元的知识与技能储备,能够从容应对复杂多变的项目需求,引领行业创新发展。于当今社会而言&#x…

SALMONN-omni论文阅读

论文链接 项目链接 名词理解: backchanneling: 指的是听话人在不打断说话人的情况下,用简短的语气词或动作表示“我在听”“我理解了”的反馈。 常见示例包括: “嗯哼”(“uh-huh”) “对的”&#xff08…

区块链:什么是DeFi?

DeFi(去中心化金融,Decentralized Finance) 是一种基于区块链技术的金融生态系统,旨在通过去中心化的方式提供传统金融服务(如借贷、交易、储蓄等),无需依赖银行、经纪商等中介机构。DeFi主要构…

idea编译器使用git拉取、提交非常慢的原因和解决方案

前言 最近在公司换了一个电脑,但是发现这个电脑用idea编译器使用git拉取、提交各种操作非常慢,有时候需要等10分钟左右,这明显是不对劲的,说明电脑的某些环境影响到git和idea之间的整合了。 目录 在idea拉取代码非常慢的原因 解决方案 在idea拉取代码非常慢的原因 经过排查…

C语言变量的奇妙世界:探秘作用域

资料合集下载链接: ​​https://pan.quark.cn/s/472bbdfcd014​​ 在C语言的编程世界里,变量是我们存储和操作数据的基础。然而,仅仅知道如何定义和使用变量是远远不够的。一个更深层次的理解,在于掌握变量的“作用域”——也就是变量在程序中可以被访问和使用的范围。这就…

恒流源和直流稳压电源 电路

目录 前言一、恒流源电路1.低端反馈2.低端反馈注意事项注意1:电阻Rx注意2:三极管和运放的限制 3.高端反馈注意:自激振荡方案二 二、直流稳压电源电流1.带反馈2.不带反馈3.区别 前言 基础知识可以看个人笔记:个人笔记 一、恒流源…

那些年,曾经辉煌过的数据库

滚滚长江东逝水,浪花淘尽英雄! 数据库的演进史,正是这样一部“英雄迭代”的壮阔史诗。从早期数据模型的拓荒者,到关系型数据库的商业巨头;从桌面应用的普及者,再到开源与大数据时代的弄潮儿;每…

2D曲线点云平滑去噪

2D曲线点云,含许多噪声,采用类似移动最小二乘的方法(MLS)分段拟合抛物线并投影至抛物线,进行点云平滑去噪。 更通俗的说法是让有一定宽度的曲线点云,变成一条细曲线上的点。 分两种情况进行讨论: 1&#…

【平面波导外腔激光器专题系列】用于精密测量的平面波导外腔激光器特性

----翻译自Kenji Numata等人的文章 摘要 1542 nm平面波导外腔激光器PW-ECL具有足够低的噪声非常适合精密测量应用。与 0.1mHz至100kHz 之间,其频率和强度噪声与非平面环形振荡器 NPRO和光纤激光器相当或更好。通过将 PW-ECL 的频率稳定在乙炔(13C2H2&a…

文件时间修改器

文件时间修改器是一款帮助用户修改文件创建时间的软件,支持毫秒级时间的修改,包括文件的创建时间、修改时间、访问时间等时间都支持修改,可以批量处理文件。 飞猫云下载 | 备用下载1 |备用下载2 基本简介 本软件主要为批量修改文件的创建时…

仓颉语言实战:MQTT物联网开发

目录 引言 mqtt4cj库的使用 申请仓颉编程语言内测 下载STDX 测试程序 结束语 引言 最近一直在学习仓颉语言,由于我对物联网比较感兴趣,自然想到写一个MQTT的程序,好在找到了mqtt4cj库,今天分享一下学习心得。 mqtt4cj库的…

OpenCV CUDA模块设备层-----用于在 CUDA 核函数中访问纹理数据的一个封装类TexturePtr()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 TexturePtr<T, R> 是 OpenCV 的 opencv_cudev 模块中用于在 CUDA 核函数中访问纹理数据的一个封装类。它主要用于将一个已创建好的 cudaTe…

Spring Boot的自动装配和自动配置

Spring Boot的自动装配&#xff08;Auto Wiring&#xff09;和自动配置&#xff08;Auto Configuration&#xff09;是两个不同的概念&#xff0c;它们在Spring框架中各自有不同的作用和用途。下面我将详细解释它们的区别和联系。 自动装配&#xff08;Auto Wiring&#xff09…

如何用 vue-office 快速搭建文档在线预览服务

1. 什么是 vue-office 1.1 vue-office 简介 vue-office 是一个基于 Vue 的组件库,用于在 Web 应用中快速集成 Office 文档的在线预览功能。它支持 Word、Excel 和 PowerPoint 等多种格式,并提供了简洁的 API 接口和丰富的自定义选项。 1.2 支持的文档类型与核心特性 支持的…

Python爬虫(六):Scrapy框架

"Scrapy到底该怎么学&#xff1f;"今天&#xff0c;我将用这篇万字长文&#xff0c;带你从零开始掌握Scrapy框架的核心用法&#xff0c;并分享我在实际项目中的实战经验&#xff01;建议收藏⭐&#xff01; 一、Scrapy简介&#xff1a;为什么选择它&#xff1f; 1.…

Linux中关闭swap分区

在 Linux 系统中关闭 swap 分区&#xff08;或交换文件&#xff09;的步骤如下&#xff0c;请务必在操作前保存所有数据&#xff0c;以免丢失&#xff1a; &#x1f4cc; 完整操作步骤&#xff1a; 1. 查看当前 swap 使用情况 free -h swapon --show # 查看活跃的 swap 设…

RPGMZ游戏引擎之如何设计每小时开启一次的副本

本文知识点 1. 获取时间 2. 时间格式要正确 3. 事件内如何设计 正文开始 1. 获取时间 首先获取当前时间 然后保存在 事件内的变量里面 后需要判断时间是否相等 function 获取当前日期(){const now new Date();return now.toISOString();}; 2. 时间格式要正确 now.toI…

学习路之uniapp--uniapp扩展uni-ui

这里写目录标题 一、新建项目二、下载导入插件三、直接创建uni-ui项目 一、新建项目 二、下载导入插件 三、直接创建uni-ui项目 创建uniapp项目时&#xff0c;直接创建uni-ui项目

Kotlin 2.6 猜数小游戏

本次实战通过开发猜数小游戏&#xff0c;深入学习了 Kotlin 编程的循环控制和条件判断。游戏要求计算机随机生成一个数字&#xff0c;用户通过输入猜测&#xff0c;程序根据猜测结果给出提示&#xff0c;直到猜中为止。通过实现这一过程&#xff0c;我们掌握了如何使用 while 循…

RNN工作原理和架构

## 1. 什么是 RNN&#xff1f; * **全称&#xff1a;** Recurrent Neural Network&#xff08;循环神经网络&#xff09; * **核心特点&#xff1a;** 它是一种专门设计用来处理**序列数据**的神经网络。 * **核心能力&#xff1a;** 拥有“记忆”能力&#xff0c;能够利用**…