likes
comments
collection
share

设计模式中的单例模式单例模式(Singleton Pattern)是一种常见的设计模式,它确保一个类只有一个实例,并提供

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

单例模式(Singleton Pattern)是一种常见的设计模式,它确保一个类只有一个实例,并提供全局访问该实例的方式。

为什么使用单例模式?

在某些情况下,我们希望一个类在应用中只存在一个实例。比如:

  • 资源共享:当某个资源(如数据库连接、浏览器存储)需要在多个地方共享时,单例模式可以确保所有地方都使用同一个实例。
  • 全局状态管理:在大型应用中,某些状态需要在多个模块间共享,单例模式可以方便地管理这些全局状态。

在 JavaScript 中,我们可以利用 ES6 的 class 语法来实现单例模式。下面我们举个栗子:

在前端开发中,我们可以通过封装 localStorage 来实现一个单例的存储类,这样可以避免重复创建实例,并统一管理浏览器的本地存储操作。

封装 Storage 类

以下是一个基于 localStorage 的单例存储类的实现。我们使用 ES6 的 class 语法,同时通过静态方法和静态属性来控制实例的创建和管理。

class Storage {
    // 静态方法,用于获取类的唯一实例
    static getInstance() {
        // 检查是否已经存在实例
        if (!Storage.instance) {
            Storage.instance = new Storage();
        }
        // 返回已存在的实例
        return Storage.instance;
    }

    // 获取 localStorage 中指定键的值
    getItem(key) {
        return localStorage.getItem(key);
    }

    // 设置 localStorage 中指定键的值
    setItem(key, value) {
        localStorage.setItem(key, value);
    }
}

export default Storage;

解毒

  • 静态方法与属性getInstance() 是一个静态方法,它负责检查 Storage 类是否已经存在一个实例。如果没有,则创建一个新的实例,并将其存储在静态属性 Storage.instance 中;如果已经存在,则直接返回该实例。
  • 实例方法getItem(key)setItem(key, value) 是实例方法,用于封装 localStoragegetItemsetItem 操作。

使用示例

在 HTML 文件中,我们可以通过如下方式导入并使用封装的 Storage 类:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Storage单例</title>
</head>
<body>
<script type="module">
    import Storage from './storage.js';

    const instance1 = Storage.getInstance();
    const instance2 = Storage.getInstance();

    // 验证两个实例是否相同
    console.log(instance1 === instance2); // 输出: true
</script>
</body>
</html>

在这个示例中,instance1instance2 都通过 Storage.getInstance() 获取,因此它们是相同的实例。无论调用多少次 getInstance(),我们得到的始终是同一个 Storage 实例,这就是单例模式的核心。

传统实现

除了使用 ES6 的 class 语法封装单例模式,我们还可以通过闭包的方式来实现:

function StorageBase() {}

StorageBase.prototype.getItem = function (key) {
    return localStorage.getItem(key);
};

StorageBase.prototype.setItem = function (key, value) {
    localStorage.setItem(key, value);
};

const Storage = (function () {
    let instance = null;
    return {
        getInstance() {
            if (!instance) {
                instance = new StorageBase();
            }
            return instance;
        },
    };
})();

虽然这种方式也能实现单例模式,但相比于 ES6 的 class 语法糖,现代实现方式更为简洁和易读。

注意事项

尽管单例模式有很多优点,但它也有一些缺点需要注意:

  • 测试困难:由于单例对象在整个应用程序中的生命周期较长,因此很难对其进行单元测试。
  • 隐藏依赖关系:单例对象可以在任何地方被访问,这使得依赖关系变得不明显,增加了维护的难度。
  • 全局状态:单例模式可能导致不期望的副作用,因为全局状态可能被任何部分修改。

结语

单例模式在大型项目中的应用十分广泛,尤其是在需要共享状态或资源时,通过单例模式可以有效地控制实例的数量,避免资源浪费和不必要的复杂性。在本文中,我们通过封装 localStorage 实现了一个简单的单例存储类,希望能为你在实际开发中提供一些参考和帮助。

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