单例模式:从弹窗管理到全局状态,一个模式搞定

发布时间:2026/8/19 23:28:33

单例模式:从弹窗管理到全局状态,一个模式搞定
从一个小事故说起不知道你有没有遇到过这样的场景用户疯狂点击打开新网页按钮结果屏幕上弹出了十几个一模一样的窗口。又或者你在项目里维护一个全局配置对象结果发现每个模块都new了一个新实例改了这个没改那个最后状态乱七八糟。这些问题背后其实指向同一个根源有些东西整个系统只需要一个。这就是我们今天要聊的单例模式Singleton Pattern。单例模式到底是什么先给个定义确保一个类只有一个实例并提供一个全局访问点。说白了就是这个类你new一百次拿到手的还是同一个对象。它解决的是全局唯一的问题——全局状态管理、资源复用、配置统一都离不开它。单例模式属于 GoF 23 种设计模式中的创建型模式跟工厂模式、建造者模式是邻居。但它的特殊之处在于别的创建型模式关心的是怎么创建它关心的是怎么不创建多个。单例模式的本质不是只能创建一个实例而是提供一个全局访问点且这个访问点背后永远只有一个实例。从一个弹窗管理器开始先看一个最经典的场景页面上有个按钮点击打开一个新窗口。我们当然不希望每次点击都window.open一发不可收拾而是希望有一个统一的弹窗管家来管理这个行为。!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title单例模式打开窗口/title /head body button idopenBtn打开新网页/button script class Popup { static ins; // 静态属性存放单例实例 static getInstance() { if (!Popup.ins) { Popup.ins new Popup(); } return Popup.ins; } open(url) { window.open(url, _blank); } } const a Popup.getInstance(); // 单例方式获取实例替代 new const b Popup.getInstance(); console.log(a b); // true证明是同一个实例 const openBtn document.getElementById(openBtn); openBtn.addEventListener(click, () { a.open(https://www.baidu.com); }); /script /body /html这段代码的核心逻辑其实就三行static getInstance() { if (!Popup.ins) { Popup.ins new Popup(); } return Popup.ins; }你会发现这就是一个惰性初始化Lazy Initialization第一次调用getInstance()时才创建实例之后直接返回缓存的那个。用a b验证一下确实是同一个对象。但问题来了这个实现有个明显的漏洞——Popup.ins是公开的谁都可以直接改Popup.ins null; // 手贱一下单例就没了 Popup.ins new Popup(); // 或者直接给你换个新的对于中级开发者来说我们得把单例这件事做得更可靠一些。更可靠的单例实现方案一闭包 IIFEconst Popup (function () { let instance; // 私有变量外部无法直接访问 class PopupClass { open(url) { window.open(url, _blank); } } return { getInstance() { if (!instance) { instance new PopupClass(); } return instance; } }; })(); const a Popup.getInstance(); const b Popup.getInstance(); console.log(a b); // true这样instance被闭包保护起来外部根本摸不到单例的唯一性就有了保障。方案二ES6 模块天然单例在 ES6 模块体系中模块本身就是单例的——无论被多少地方import模块代码只执行一次导出的对象永远是同一个。// popup.js class Popup { open(url) { window.open(url, _blank); } } export const popupInstance new Popup();// 任何地方使用 import { popupInstance } from ./popup.js; popupInstance.open(https://www.baidu.com);这种方式简单粗暴也是前端工程化中最常用的单例实现方式。你项目里的 Axios 实例、WebSocket 连接、Vuex/Pinia Store本质上都是这么玩的。方案三Symbol 做私有 key如果你想继续用 Class 的写法但又想保护ins不被随意访问可以用 Symbolconst INS Symbol(singleton); class Popup { static getInstance() { if (!Popup[INS]) { Popup[INS] new Popup(); } return Popup[INS]; } open(url) { window.open(url, _blank); } }Symbol作为属性 key 不会被常规遍历发现也不会跟其他属性冲突。不过说实话在 JS 里防君子不防小人真要改还是能通过Object.getOwnPropertySymbols拿到。所以工程实践中方案二ES6 模块才是最主流的选择。单例模式在前端的高频落地场景理论讲完了来看看真实项目中单例模式都在哪里打工。场景一全局状态管理Pinia / Vuex你用 Pinia 定义的 Store本质上就是一个单例。不管在哪个组件里调用useUserStore()拿到的都是同一个实例状态自然就同步了。// stores/user.js import { defineStore } from pinia; export const useUserStore defineStore(user, { state: () ({ name: , token: }), actions: { setUser(user) { this.name user.name; this.token user.token; } } });Pinia 内部保证了同一个 id 的 Store 只会被创建一次——这就是单例模式在框架层面的应用。场景二Axios 实例封装几乎每个前端项目都会封装一个统一的 HTTP 客户端// utils/request.js import axios from axios; const request axios.create({ baseURL: /api, timeout: 10000, }); // 请求拦截器 request.interceptors.request.use(config { config.headers.Authorization localStorage.getItem(token) || ; return config; }); export default request;整个项目共享这一个 Axios 实例好处显而易见拦截器配置一次、Token 注入一处、错误处理统一。如果每个模块都自己axios.create一个那你改拦截器就要改到怀疑人生。场景三WebSocket 连接管理一个页面通常只需要一条 WebSocket 连接。如果每次组件挂载都new WebSocket()服务端可能会因为连接数爆掉而把你拉黑。// utils/socket.js class SocketManager { static instance null; static getInstance() { if (!SocketManager.instance) { SocketManager.instance new SocketManager(); } return SocketManager.instance; } connect(url) { if (this.ws this.ws.readyState WebSocket.OPEN) { return this.ws; // 已连接直接复用 } this.ws new WebSocket(url); return this.ws; } } export default SocketManager;单例模式的阴暗面聊完了好处也得说实话。单例模式在江湖上有个外号叫披着设计模式外衣的全局变量它确实有一些需要警惕的地方。问题一隐藏的耦合单例是全局可访问的这意味着任何模块都可以依赖它。如果滥用你的代码会变成一张谁也理不清的依赖网。问题二难以测试因为单例是全局唯一的在单元测试中很难重置它的状态。你测完一个用例单例的脏数据可能影响下一个用例。问题三违反单一职责原则单例类往往既要管自己的业务逻辑又要管自己只能有一个实例这件事。这在大型项目中会让类的职责变重。设计模式不是银弹单例用好了是全局状态管理利器用不好就是隐藏的全局变量灾难。什么时候该用单例给你一个简单的判断标准✅ 资源本身在业务上就是唯一的如全局配置、日志收集器、数据库连接池、WebSocket 连接✅ 创建成本高且可以复用如线程池在 JS 中更多是连接池、缓存管理器❌ 仅仅因为方便就把普通对象改成单例比如用户信息、购物车数据这些应该交给状态管理工具Pinia/Vuex/Redux而不是手动实现单例总结这篇文章从一个弹窗管理的例子出发聊了单例模式的核心思想、多种实现方式以及在前端工程中的真实应用场景。来一张图帮你快速回顾实现方式适用场景私有性Class 静态方法简单场景、教学演示❌ 属性公开闭包 IIFE需要保护实例引用✅ 私有变量ES6 模块导出实例工程实践首选✅ 天然单例Symbol 属性需要 Class 写法 一定保护⚠️ 半私有核心就一句话确保一个类只有一个实例并提供一个全局访问点。下次当你发现某个对象整个项目只需要一个的时候别犹豫单例模式安排上。但也要记得模式是工具不是信仰——适合的才是最好的。

相关新闻

linux网络:TCP套接字基础

linux网络:TCP套接字基础

2026/8/19 23:28:33

我们直接从一个简单的测试入手一、准备工作我们先把代码放出来,然后对着代码进行分析1、用户类class InetAddr { public:InetAddr(struct sockaddr_in&addr):_addr(addr){//网络转主机_portntohs(_addr.sin_port);//从网络中拿到网络序列char ipbuffer[64];inet…

wordpress添加javascript

wordpress添加javascript

2026/8/19 23:28:33

------添加------custom html---------选择js

HarmonyOS 7.0 / API 26 空间音频兜底:耳机能力不一致时播放链路怎么切回普通模式

HarmonyOS 7.0 / API 26 空间音频兜底:耳机能力不一致时播放链路怎么切回普通模式

2026/8/19 23:28:33

先看问题为什么会发生 这篇只抓一个点:空间音频能力兜底。我不按概念顺序铺开,而是按项目里最容易出问题的路径来拆:先复现坏写法,再补上边界判断,最后用日志和状态验证结果。 空间音频的坑不在播放,而在不…

告别命令行焦虑:RedisDesktopManager Windows版下载安装与使用全指南

告别命令行焦虑:RedisDesktopManager Windows版下载安装与使用全指南

2026/8/20 0:18:45

告别命令行焦虑:RedisDesktopManager Windows版下载安装与使用全指南 【免费下载链接】RedisDesktopManager-Windows RedisDesktopManager Windows版本 项目地址: https://gitcode.com/gh_mirrors/re/RedisDesktopManager-Windows 如果你还在用 redis-cli 一…

黑苹果触摸板手势失灵怎么办?5步调校找回丝滑体验

黑苹果触摸板手势失灵怎么办?5步调校找回丝滑体验

2026/8/20 0:18:45

黑苹果触摸板手势失灵怎么办?5步调校找回丝滑体验 【免费下载链接】Hackintosh Hackintosh long-term maintenance model EFI and installation tutorial 项目地址: https://gitcode.com/gh_mirrors/ha/Hackintosh 系统装好了,你的黑苹果&#xf…

VASPsol隐式溶剂模型实操指南:从真空DFT到溶剂化计算的完整避坑路线

VASPsol隐式溶剂模型实操指南:从真空DFT到溶剂化计算的完整避坑路线

2026/8/20 0:18:45

VASPsol隐式溶剂模型实操指南:从真空DFT到溶剂化计算的完整避坑路线 【免费下载链接】VASPsol Solvation model for the plane wave DFT code VASP. 项目地址: https://gitcode.com/gh_mirrors/va/VASPsol 如果有一件事能让一位材料计算研究者的周末彻底泡汤…

免费开源多视频网格播放器GridPlayer:3步破解多视频对比难题

免费开源多视频网格播放器GridPlayer:3步破解多视频对比难题

2026/8/20 0:18:45

免费开源多视频网格播放器GridPlayer:3步破解多视频对比难题 【免费下载链接】gridplayer Play videos side-by-side 项目地址: https://gitcode.com/gh_mirrors/gr/gridplayer 深夜改稿的你,是不是也干过这种事:为了对比两个剪辑版本…

book118文档下载工具实测:一个文档编号,把只能在线预览的资料免费存成本地PDF

book118文档下载工具实测:一个文档编号,把只能在线预览的资料免费存成本地PDF

2026/8/20 0:18:45

book118文档下载工具实测:一个文档编号,把只能在线预览的资料免费存成本地PDF 【免费下载链接】book118-downloader 基于java的book118文档下载器 项目地址: https://gitcode.com/gh_mirrors/bo/book118-downloader 在Book118上翻到一份刚好能预览…

告别乱码:CK2dll 双字节补丁让《十字军之王II》中文显示正常的完整上手指南

告别乱码:CK2dll 双字节补丁让《十字军之王II》中文显示正常的完整上手指南

2026/8/20 0:08:45

告别乱码:CK2dll 双字节补丁让《十字军之王II》中文显示正常的完整上手指南 【免费下载链接】CK2dll Crusader Kings II double byte patch /production : 3.3.4 /dev : 3.3.4 项目地址: https://gitcode.com/gh_mirrors/ck/CK2dll 很多中文玩家第一次接触《…

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

2026/8/19 3:36:59

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

【双层规划,节点出清价,绿证交易,CVaR方法】两级电力市场环境下计及风险的省间交易商最优购电模型附Matlab代码

【双层规划,节点出清价,绿证交易,CVaR方法】两级电力市场环境下计及风险的省间交易商最优购电模型附Matlab代码

2026/8/19 9:17:18

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

隐式mpc+自适应mpc+时变mpc,线性时变模型预测控制附Simulink仿真

隐式mpc+自适应mpc+时变mpc,线性时变模型预测控制附Simulink仿真

2026/8/19 8:02:16

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

微信聊天记录如何完整导出?WeChatMsg备份指南:HTML/Word/CSV一键转换

微信聊天记录如何完整导出?WeChatMsg备份指南:HTML/Word/CSV一键转换

2026/8/20 0:08:45

微信聊天记录如何完整导出?WeChatMsg备份指南:HTML/Word/CSV一键转换 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com…

B站缓存m4s打不开?m4s-converter无损合成MP4,实测1.46GB仅5秒

B站缓存m4s打不开?m4s-converter无损合成MP4,实测1.46GB仅5秒

2026/8/20 0:08:45

B站缓存m4s打不开?m4s-converter无损合成MP4,实测1.46GB仅5秒 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 判断你是否…

告别白模时代:Blender3mfFormat 让 3MF 导入导出一次跑通设计到打印

告别白模时代:Blender3mfFormat 让 3MF 导入导出一次跑通设计到打印

2026/8/20 0:08:45

告别白模时代:Blender3mfFormat 让 3MF 导入导出一次跑通设计到打印 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat 按 3MF 官方规范的字面意思,一…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/17 12:00:53

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/15 10:10:27

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/18 12:20:24

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…