likes
comments
collection
share

代码优雅之道——聊聊单例模式

作者站长头像
站长
· 阅读数 48

前言

单例模式是一种设计模式,确保类只有一个实例,并提供全局访问点。在 JavaScript 中,可以通过立即执行函数和闭包来创建单例,从而避免多次实例化和资源浪费。通过单例模式,可以方便地管理全局状态和共享资源,提高代码的可维护性和可扩展性。

话题引入

代码优雅之道——聊聊单例模式

我们首先看这段代码,我们知道两者肯定不会相等,那么有没有一种方法,让我们可以创建两个完全一样的对象呢?

方法一

代码优雅之道——聊聊单例模式

我们定义一个静态方法,如果没有创建实例(构造函数的属性不存在)我们就创建一个实例,并且作为构造函数的属性,已经存在我们就直接返回这个属性。

方法二

代码优雅之道——聊聊单例模式

我们还可以使用闭包,具体操作是设置了一个只有构造函数本身可以访问的方法,我们通过闭包的方式返回出一个函数体,函数体内返回值。

代码优雅之道——聊聊单例模式

这样子的话,我们就会发现两者是完全一样的啦!

单例模式应用一

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <button id="save">存储</button>
  <button id="get">取值</button>

  <script>
    let save = document.getElementById('save')
    let get = document.getElementById('get')

    class Storage {
      static getInstance() {
        if (!Storage.instance) {
          Storage.instance = new Storage()
        }
        return Storage.instance
      }
      getItem(key) {
        return localStorage.getItem(key)
      }
      setItem(key, val) {
        return localStorage.setItem(key, val)
      }
    }

    const storage = Storage.getInstance()
    const storage2 = Storage.getInstance()

    save.onclick = function () {
      // localStorage.setItem('name', '高老师')
      storage.setItem('name', '高老师')
    }

    get.onclick = function () {
      alert(storage2.getItem('name'))
    }

  </script>
</body>

</html>

比如如果要我们去手写本地存储。要想让Storage达到和localStorage一样的效果,我们采用的是非闭包方法,我们这个时候的两个storage对象是一样的,因此我们可以实现正常的赋值取值。这个时候就实现了和之前一样的效果。

单例模式应用二

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      text-align: center;
    }

    #model {
      position: fixed;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 200px;
      height: 200px;
      border: 1px solid #000;
      line-height: 200px;
      display: none;
    }
  </style>
</head>

<body>
  <button id="open">打开弹框</button>
  <button id="close">关闭弹框</button>
  <!-- <div id="model">
    我是弹出框
  </div> -->

  <script>
    const Model = (function () {
      let model = null
      return function () {
        if (!model) {
          model = document.createElement('div')
          model.innerHTML = '我是全局唯一的弹框'
          model.id = 'model'
          model.style.display = 'none';
          document.body.appendChild(model)
        }
        return model
      }
    })()


    document.getElementById("open").addEventListener("click", () => {
      const model = new Model()
      model.style.display = 'block'
    });
    document.getElementById("close").addEventListener("click", () => {
      const model = new Model()
      model.style.display = 'none'
    });
  </script>
</body>

</html>

首先我们要知道如果全文需要多个相同的弹框,我们不必设置每一个,只需要设置一个。大家用的时候直接调用就可以,这里我们采用了闭包的方式,model就是一个自执行函数的结果,最后返回model,因此我们最终调用的model都是同一个。

小结

在 JavaScript 中,单例模式用于确保一个类只有一个实例,并提供一个全局访问点。通常使用闭包来实现单例模式,通过立即执行函数和私有变量来封装实例化过程,从而避免多次创建实例和资源浪费。单例模式能够有效地管理全局状态和共享资源,提高代码的可维护性和可扩展性。它常用于创建唯一的对象,例如应用程序的配置信息、日志记录器、缓存等。同时,单例模式还可以结合惰性单例模式,延迟实例化过程,直到真正需要时才进行实例化。在现代 JavaScript 中,单例模式可以与模块化开发相结合,通过模块化方案(如ES6 模块)来管理单例对象。因此,了解单例模式的概念和实现方式对于构建高效、可维护的 JavaScript 应用程序是非常重要的。

转载自:https://juejin.cn/post/7377298855228260387
评论
请登录