百度考题之单例模式

浅聊一下

设计模式是我们必不可少的编程素养,今天我们要聊的是百度考题------单例模式

es6新增 "类"

要讲单例模式,我们就从es6新增的类开始说起,我们先来看代码

js 复制代码
class SingleDog{
    show(){
        console.log('我是一个单例对象');
    }
}

const s1 = new SingleDog();
const s2 = new SingleDog();

console.log(s1 === s2);

这段代码定义了一个类,名字叫SingleDog,我们创建了两个SingleDog的实例对象s1和s2,打印一下他们的结果,这并不难理解,因为创建的s1和s2所存储的地址不同,他们是相同类的不同实例对象,于是乎,打印的结果肯定是 false

那么跟我们今天要讲的单例模式有什么关系呢?我们先来了解一下单例模式到底是什么...

单例模式

当我们谈论单例模式时,我们指的是一种设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来访问该实例。

什么意思?就是说在我上面的SingleDog类只能有一个实例对象,不管你创建了多少个对象,都会返回创建的第一个对象...那该咋办?我们得用到static

static

在 JavaScript 中,static 是一个关键字,用于定义类的静态属性和静态方法。静态成员属于类本身,而不是类的实例。

讲的这么深奥,我还是看不懂...那就直接上代码

js 复制代码
class SingleDog{
    //属于对象的
    show(){
        console.log('我是一个单例对象');
    
    }
    // 不要直接new 
    // 属于类的
    static getInstance(){
        console.log('静态方法');    
    }
}

当我们要使用show()方法时,我们得创建一个SingleDog的实例对象,然后再通过实例对象来调用show()方法

js 复制代码
const s1 = new SingleDog()
s1.show()

而当我们想要调用static方法的时候,不用创建直接调用

js 复制代码
SingleDog.getInstance()

实现单例模式

我们已经掌握了static,那么我们怎么来实现单例模式呢?

js 复制代码
class SingleDog{
    //属于对象的
    show(){
        console.log('我是一个单例对象');
    
    }
    // 不要直接new 
    // 属于类的
    static getInstance(){
        // console.log('静态方法');
        if(!SingleDog.instance){
            SingleDog.instance = new SingleDog();
        }
        return SingleDog.instance;
    }
}

static getInstance 是一个静态方法,它属于类本身而不是类的实例。通过 static 关键字声明的静态方法可以直接通过类名调用,无需创建类的实例。在这个例子中,getInstance 方法的作用是返回 SingleDog 类的一个实例。

  • getInstance 方法内部,首先检查静态属性 instance 是否已经存在实例。如果不存在,就创建一个新的 SingleDog 实例,并将其赋值给 instance 属性。
  • 随后,无论是否创建了新实例,都会返回 instance 属性的值,确保始终返回同一个实例。

通过这种设计,你可以确保 SingleDog 类的实例始终只有一个,因为 getInstance 方法在每次调用时都会返回相同的实例。这就是所谓的单例模式,它确保一个类只有一个实例,并提供了一个全局访问点以确保所有代码都在使用相同的实例。

使用静态方法来实现单例模式是一种常见的做法,因为它允许你在不创建实例的情况下访问类的方法,并且能够控制类的实例化过程。

百度考题-写一个弹窗

百度考题呀,让你写一个弹窗,实际上就是要你写一个单例模式,你点击一个按钮,弹出弹窗,点击关闭,弹窗关闭,无论你点击多少个按钮,无论你点击多少次按钮,弹窗始终是最开始的那个弹窗...

理解了上面讲的内容,想要写出来并不难

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录框</title>
    <style>
        #modal{
            width: 200px;
            height: 200px;
            background-color: #ccc;
            line-height: 200px;
            text-align: center;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
            border: 1px solid #000;          
        }
    </style>
</head>
<body>
    <button id="open">打开弹窗</button>
    <button id="close">关闭弹窗</button>
    <script>
        //立即执行函数
        // 闭包的方式实现单例
        const Modal = (function(){
            //创建闭包
            let modal = null//自由变量
            return function(){
                if(!modal){
                    modal = document.createElement('div')
                    modal.innerHTML = '我是全局唯一的登录框'
                    modal.style.display = 'none'
                    modal.id = 'modal'
                    document.body.appendChild(modal)
                }
                return modal
            }
        })()
        // const modal = new Modal()
        document.getElementById('open').addEventListener('click',function(){
            const modal = new Modal();
            modal.style.display = 'block'
        })
        document.getElementById('close').addEventListener('click',function(){
            const modal = new Modal();
            modal.style.display = 'none'
        })
    </script>
</body>
</html>
  1. 定义立即执行函数
js 复制代码
const Modal = (function(){ 
    // ... 
})()

这里定义了一个匿名函数,并立即执行它。由于括号 () 包裹在函数声明的外部,所以该函数会立即执行。同时,在函数内部定义了一个闭包,用于实现单例模式。

  1. 创建闭包
js 复制代码
let modal = null; 
return function() {
    // ... 
}

在闭包内部,定义了一个自由变量 modal,初始值为 null。然后,返回一个函数,该函数可以访问并操作 modal 变量,也就是实现了闭包。如果还有不会闭包的掘友可以去看我的文章(深入探讨:闭包的神秘面纱 - 掘金 (juejin.cn))

  1. 实现单例模式
js 复制代码
if (!modal) {
modal = document.createElement('div'); 
// ... 
return modal; 
}

在闭包内部的函数中,首先判断 modal 变量是否已经存在。如果不存在,则创建登录框元素,并将其添加到 body 中,然后将 modal 变量赋值为该元素。最后,返回 modal 变量。这样,下次再调用该函数时,就会直接返回之前创建的登录框元素,而不会重复创建。

  1. 使用单例模式
js 复制代码
document.getElementById('open').addEventListener('click', function() { 
const modal = new Modal(); 
modal.style.display = 'block'; 
}); 
document.getElementById('close').addEventListener('click', function() { 
const modal = new Modal();
modal.style.display = 'none'; 
});

在页面中,有两个按钮,一个用于打开登录框,一个用于关闭登录框。当用户点击打开按钮时,代码会调用 Modal 函数来获取或创建登录框元素,然后将其显示出来。当用户点击关闭按钮时,代码也调用 Modal 函数来获取或创建登录框元素,然后将其隐藏。

来看看效果:

点击打开弹窗,new了一个新的DOM结点,此时display为block

点击关闭弹窗,让DOM结点display为none

再次点击打开弹窗,不会新建一个DOM,而是让原来的DOMdisplay为block...题目完成

结尾

在实际应用中,合理地运用设计模式能够提高代码质量、可读性和可维护性,是每个开发者都应该掌握的技能之一。希望本篇内容能对你有所帮助,如果有任何疑问或者想继续探讨其他主题,都可以随时提出哦!

相关推荐
EricWang135815 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning15 分钟前
React.lazy() 懒加载
前端·react.js·前端框架
时差95319 分钟前
【面试题】Hive 查询:如何查找用户连续三天登录的记录
大数据·数据库·hive·sql·面试·database
web行路人25 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
番茄小酱00126 分钟前
Expo|ReactNative 中实现扫描二维码功能
javascript·react native·react.js
子非鱼9211 小时前
【Ajax】跨域
javascript·ajax·cors·jsonp
超雄代码狂1 小时前
ajax关于axios库的运用小案例
前端·javascript·ajax
长弓三石1 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
小马哥编程1 小时前
【前端基础】CSS基础
前端·css
嚣张农民1 小时前
推荐3个实用的760°全景框架
前端·vue.js·程序员