js单例模式

单例模式是一种常见的设计模式,在JavaScript中也有广泛应用,以下是关于它的详细介绍:

定义

  • 单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。在JavaScript中,虽然没有像传统面向对象语言中的类的概念,但可以通过对象字面量、构造函数、闭包等方式来实现单例模式。

实现方式

对象字面量方式

javascript 复制代码
const singleton = {
    property: "Some value",
    method: function() {
        console.log("This is a method in the singleton object.");
    }
};
  • 这种方式简单直接,创建了一个包含属性和方法的对象字面量,并且该对象在全局范围内只有一个实例。可以通过 singleton.propertysingleton.method() 来访问和调用其中的成员。

构造函数与闭包结合方式

javascript 复制代码
function Singleton() {
    if (!Singleton.instance) {
        Singleton.instance = this;
        this.property = "Some value";
        this.method = function() {
            console.log("This is a method in the singleton instance.");
        };
    }
    return Singleton.instance;
}

const instance1 = new Singleton();
const instance2 = new Singleton();

console.log(instance1 === instance2); // true
  • 在构造函数 Singleton 内部,通过判断 Singleton.instance 是否存在来确保只有一个实例被创建。如果不存在,则将当前实例赋值给 Singleton.instance ,并添加属性和方法。后续每次调用 new Singleton() 时,都会返回同一个实例。

使用ES6的类和静态属性

javascript 复制代码
class Singleton {
    constructor() {
        if (!Singleton.instance) {
            Singleton.instance = this;
            this.property = "Some value";
            this.method = function() {
                console.log("This is a method in the singleton instance.");
            };
        }
        return Singleton.instance;
    }

    static getInstance() {
        if (!Singleton.instance) {
            Singleton.instance = new Singleton();
        }
        return Singleton.instance;
    }
}

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

console.log(instance1 === instance2); // true
  • 定义了一个 Singleton 类,在构造函数中同样进行实例的唯一性判断和创建。同时,提供了一个静态方法 getInstance ,用于获取单例实例,这样可以更方便地在其他地方获取单例对象,而不需要直接调用构造函数。

应用场景

全局状态管理

  • 在JavaScript应用中,如Vuex、Redux等状态管理库的核心原理就部分地运用了单例模式。以Vuex为例,整个应用中的状态存储在一个唯一的store实例中,各个组件都可以访问和修改这个store中的状态,确保了状态的一致性和唯一性。
javascript 复制代码
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        increment(state) {
            state.count++;
        }
    }
});

export default store;

数据库连接池

  • 在与数据库交互的应用中,为了避免频繁地创建和销毁数据库连接,通常会使用数据库连接池来管理连接。连接池可以设计成单例模式,确保整个应用中只有一个连接池实例,所有需要数据库连接的地方都从这个连接池中获取连接,提高性能和资源利用率。
javascript 复制代码
const mysql = require('mysql');

class DatabasePool {
    constructor() {
        if (!DatabasePool.instance) {
            this.pool = mysql.createPool({
                connectionLimit: 10,
                host: 'localhost',
                user: 'root',
                password: 'password',
                database: 'mydb'
            });
            DatabasePool.instance = this;
        }
        return DatabasePool.instance;
    }

    getConnection(callback) {
        this.pool.getConnection(callback);
    }
}

const pool = new DatabasePool();
pool.getConnection((err, connection) => {
    if (err) throw err;
    // 使用连接进行数据库操作
    connection.release();
});

日志记录器

  • 在应用中,通常需要一个统一的日志记录器来记录各种操作和错误信息。单例模式可以确保整个应用中只有一个日志记录器实例,方便对日志进行统一管理和配置,避免多个日志记录器之间的冲突和混乱。
javascript 复制代码
class Logger {
    constructor() {
        if (!Logger.instance) {
            this.logs = [];
            Logger.instance = this;
        }
        return Logger.instance;
    }

    log(message) {
        const timestamp = new Date().toISOString();
        this.logs.push(`${timestamp} - ${message}`);
        console.log(message);
    }

    getLogs() {
        return this.logs;
    }
}

const logger = new Logger();
logger.log("This is a log message.");
logger.log("Another log message.");
console.log(logger.getLogs());

优点

  • 确保唯一性:保证一个类只有一个实例存在,避免了因创建多个实例而导致的资源浪费和数据不一致等问题。
  • 全局访问点:提供了一个全局可访问的点来获取该实例,方便在不同的模块和代码位置共享和使用该实例,提高了代码的可维护性和可扩展性。

缺点

  • 违反单一职责原则:单例类可能会承担过多的职责,因为它既要负责自身的实例化和管理,又要提供各种业务方法和属性,导致类的职责不单一,不利于代码的维护和测试。
  • 隐藏依赖关系:由于单例模式通常提供全局访问点,使得代码中对单例实例的依赖关系变得不明显,可能会导致代码的耦合度增加,不利于代码的解耦和重构。
相关推荐
Code成立10 分钟前
《Java核心技术II》简单约简
java·开发语言·python
Bony-18 分钟前
Go语言中的逃逸分析:深入浅出
开发语言·后端·golang
Jiaberrr31 分钟前
页面转 PDF 功能的实现思路与使用方法
前端·javascript·vue.js·微信小程序·pdf·uniapp
码农多耕地呗33 分钟前
Java.函数-acwing
java·开发语言
lsx20240639 分钟前
Linux vi/vim 编辑器:功能强大的文本处理工具
开发语言
阿珊和她的猫39 分钟前
JavaScript中的内存泄露:识别与避免
开发语言·javascript·ecmascript
lennon_jlu1 小时前
1.4 java反射机制 简单的java反射机制实践
java·开发语言·python
luoluoal1 小时前
java项目之社区医院信息平台源码(springboot+mysql)
java·开发语言
pchmi1 小时前
C# OpenCV机器视觉:背景减除与前景分离
javascript·opencv·c#
从以前1 小时前
解析 World Football Cup 问题及其 Python 实现
开发语言·python·算法