—— 从理论到实战)
什么是单例模式单例模式是OOP面向对象编程中最经典的设计模式之一属于 GoF 23 种设计模式中的一种。核心思想一个类在系统中只能被实例化一次无论调用多少次返回的都是同一个实例。单例模式常用于解决以下场景 场景说明全局状态管理整个应用只需要一个管理器如 Vuex Store、Redux Store弹窗/窗口控制页面中只允许打开一个弹窗窗口数据库连接池避免重复创建昂贵的连接资源缓存管理全局共享同一份缓存数据 为什么需要单例模式假设我们不用单例模式每次需要弹窗时都new一个新对象constanewPopup();constbnewPopup();console.log(ab);// ❌ false —— 这是两个完全不同的实例这意味着每次点击按钮都会创建一个新的弹窗对象如果对象内部持有大量资源DOM引用、网络连接等就会造成内存浪费—— 重复创建不需要的对象状态不一致—— 多个实例各自维护状态互相不同步行为不可控—— 比如重复打开多个窗口单例模式正是为了确保全局只有一个实例而存在的。✅ 单例模式的实现下面是一个最简洁、最经典的 JavaScript 单例模式实现classPopup{staticins;// ⬅️ 静态属性存储唯一的实例staticgetInstance(){if(!Popup.ins){Popup.insnewPopup();// 第一次调用时创建实例}returnPopup.ins;// 后续调用直接返回已有实例}open(url){window.open(url,_blank);}} 三个关键要素要素代码作用① 静态属性static ins作为类级别的存储容器不绑定到任何实例② 延迟初始化if (!Popup.ins)只在首次调用时才创建实例惰性加载③ 静态方法static getInstance()提供统一的获取入口替代new关键字⚠️注意不要在声明静态属性时直接赋值static ins new Popup()这会导致类加载时就立即实例化失去了延迟初始化的优势。 验证真的是同一个实例吗constaPopup.getInstance();// 第一次获取constbPopup.getInstance();// 第二次获取console.log(ab);// ✅ true —— a 和 b 指向同一个对象用一张图来理解调用 getInstance() │ ▼ ┌──────────┐ │ ins 存在 │ └─────┬────┘ │ ┌────┴────┐ No Yes │ │ ▼ ▼ new Popup() 直接返回 ins │ ▼ 赋值给 ins然后返回无论调用多少次getInstance()始终返回的是同一个Popup实例。️ 完整实战单例模式打开窗口将单例模式应用到实际的页面交互中!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0title单例模式打开窗口/title/headbodybuttonidopenBtn打开窗口/buttonscript// ① 定义单例类 classPopup{staticins;staticgetInstance(){if(!Popup.ins){Popup.insnewPopup();}returnPopup.ins;}open(url){window.open(url,_blank);}}// ② 通过 getInstance 获取实例代替 new constpopupPopup.getInstance();// ③ 绑定事件 constopenBtndocument.getElementById(openBtn);openBtn.addEventListener(click,(){popup.open(https://www.baidu.com);});/script/body/html为什么不用new Popup()使用getInstance()能够保证全局只有一个实例。如果用new每次都会创建新对象就失去了单例的意义。 单例模式的优缺点✅ 优点全局唯一—— 保证系统中该类只有一个实例节省资源—— 避免重复创建和销毁对象状态共享—— 所有使用者访问同一个实例状态天然同步❌ 缺点违反单一职责—— 类既要负责业务逻辑又要管理自己的实例化测试困难—— 全局状态可能导致测试之间互相影响不够灵活—— 一旦实现为单例后续难以扩展为多实例 总结维度内容是什么保证一个类只有一个实例并提供全局访问点怎么实现static属性存储实例 getInstance()延迟初始化核心判断if (!Instance)→ 不存在则创建存在则直接返回适用场景弹窗管理、全局状态、连接池、缓存等一句话用getInstance()代替new全局只有一个对象 单例模式虽然简单却是学习设计模式的绝佳入口。掌握了它你就迈出了从写代码到设计代码的第一步。