保证一个类仅有一个实例,并提供一个访问它的全局访问点,这样的模式就叫做单例模式。
单例模式的实现思路
现在我们先不考虑单例模式的应用场景,单看它的实现,思考这样一个问题:如何才能保证一个类仅有一个实例?
一般情况下,当我们创建了一个类(本质是构造函数)后,可以通过new关键字调用构造函数进而生成任意多的实例对象。像这样:
class SingleDog { show() { console.log('我是一个单例对象') } } const s1 = new SingleDog() const s2 = new SingleDog() // false s1 === s2
楼上我们先 new 了一个 s1,又 new 了一个 s2,很明显 s1 和 s2 之间没有任何瓜葛,两者是相互独立的对象,各占一块内存空间。而单例模式想要做到的是,不管我们尝试去创建多少次,它都只给你返回第一次所创建的那唯一的一个实例。
要做到这一点,就需要构造函数具备判断自己是否已经创建过一个实例的能力。我们现在把这段判断逻辑写成一个静态方法(其实也可以直接写入构造函数的函数体里):
class SingleDog { show() { console.log('我是一个单例对象') } static getInstance() { // 判断是否已经new过1个实例 if (!SingleDog.instance) { // 若这个唯一的实例不存在,那么先创建它 SingleDog.instance = new SingleDog() } // 如果这个唯一的实例已经存在,则直接返回 return SingleDog.instance } } const s1 = SingleDog.getInstance() const s2 = SingleDog.getInstance() // true s1 === s2
除了楼上这种实现方式之外,getInstance的逻辑还可以用闭包来实现:
SingleDog.getInstance = (function() { // 定义自由变量instance,模拟私有变量 let instance = null return function() { // 判断自由变量是否为null if(!instance) { // 如果为null则new出唯一实例 instance = new SingleDog() } return instance } })()
可以看出,在getInstance方法的判断和拦截下,我们不管调用多少次,SingleDog都只会给我们返回一个实例,s1和s2现在都指向这个唯一的实例。
两种方法都有一个共同的特性,就是不要直接new,而是通过一个方法去返回实例,当这个实例没有创建的时候就new一个对象,否则就返回已经创建的实例,这样就达到了单例模式
实现一个全局的模态框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>单例模式弹框</title> </head> <style> #modal { height: 200px; width: 200px; line-height: 200px; position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); border: 1px solid black; text-align: center; } </style> <body> <button id='open'>打开弹框</button> <button id='close'>关闭弹框</button> </body> <script> // 核心逻辑,这里采用了闭包思路来实现单例模式 const Modal = (function () { let modal = null return function () { if (!modal) { modal = document.createElement('div') modal.innerHTML = '我是一个全局唯一的Modal' modal.id = 'modal' modal.style.display = 'none' document.body.appendChild(modal) } return modal } })() // 点击打开按钮展示模态框 document.getElementById('open').addEventListener('click', function () { // 未点击则不创建modal实例,避免不必要的内存占用;此处不用 new Modal 的形式调用也可以,和 Storage 同理 const modal = new Modal() modal.style.display = 'block' }) // 点击关闭按钮隐藏模态框 document.getElementById('close').addEventListener('click', function () { const modal = new Modal() if (modal) { modal.style.display = 'none' } }) </script> </html>
发表评论
侧栏公告
寄语
譬如朝露博客是一个分享前端知识的网站,联系方式11523518。
热评文章
标签列表
热门文章
友情链接