设计模式 - 单例

发布于:2025-04-15 ⋅ 阅读:(20) ⋅ 点赞:(0)

单例设计模式

单例设计模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。
在 JavaScript 里,有多种实现单例设计模式的方式,下面为你详细介绍:

1. 简单对象字面量实现

  • 这是最简单的单例实现方式,利用对象字面量创建一个对象,该对象在整个应用程序里只会有一个实例。
const singleton = {
    property: 'value',
    method: function() {
        return this.property;
    }
};

// 使用单例
console.log(singleton.method());

2. 构造函数结合闭包实现

  • 借助构造函数和闭包保证类只有一个实例。
const Singleton = (function() {
    let instance;

    function createInstance() {
        const object = {
            property: 'value',
            method: function() {
                return this.property;
            }
        };
        return object;
    }

    return {
        getInstance: function() {
            if (!instance) {
                instance = createInstance();
            }
            return instance;
        }
    };
})();

// 使用单例
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // 输出: true

在这个例子中,Singleton 是一个立即执行函数,返回一个包含 getInstance 方法的对象。getInstance 方法会检查 instance 是否已经存在,若不存在则创建一个新实例,若存在则返回已有的实例。

3. ES6 类实现

  • 在 ES6 中,可以使用类和静态方法来实现单例模式。
class Singleton {
    constructor() {
        if (!Singleton.instance) {
            this.property = 'value';
            Singleton.instance = this;
        }
        return Singleton.instance;
    }

    method() {
        return this.property;
    }
}

// 使用单例
const instance3 = new Singleton();
const instance4 = new Singleton();
console.log(instance3 === instance4); // 输出: true

// 在这个例子中,Singleton 类的构造函数会检查 Singleton.instance 是否已经存在,
// 若不存在则创建一个新实例并将其赋值给 Singleton.instance,若存在则返回已有的实例。

4. 使用 WeakMap 实现

  • WeakMap 可用来存储对象的私有数据,能够借助它实现单例模式,保证单例的私有性。
const Singleton = (function() {
    const instanceMap = new WeakMap();

    class SingletonClass {
        constructor() {
            if (instanceMap.has(this)) {
                return instanceMap.get(this);
            }
            this.property = 'value';
            instanceMap.set(this, this);
        }

        method() {
            return this.property;
        }
    }

    return SingletonClass;
})();

// 使用单例
const instance1 = new Singleton();
const instance2 = new Singleton();
console.log(instance1 === instance2); 

在这个示例中,运用 WeakMap instanceMap 来存储单例实例。当创建 SingletonClass 的新实例时,会先检查 instanceMap 里是否已有该实例,若有则返回已有实例,若无则创建新实例并将其存入 instanceMap。

5. 模块模式实现

在 JavaScript 模块系统里,模块只会被加载一次,这就保证了模块内部的变量和函数只有一个实例,能够利用这个特性实现单例模式。

// singletonModule.js
const singleton = {
    property: 'value',
    method: function() {
        return this.property;
    }
};
export default singleton;


// main.js
import singleton from './singletonModule.js';

console.log(singleton.method()); 

6. 使用 Proxy 实现

  • 可以借助 Proxy 来拦截对象的创建过程,以此保证对象只有一个实例。
const Singleton = new Proxy(function() {}, {
    instance: null,
    construct(target, args) {
        if (!this.instance) {
            this.instance = new target(...args);
        }
        return this.instance;
    }
});

class MyClass {
    constructor() {
        this.property = 'value';
    }

    method() {
        return this.property;
    }
}

const instance1 = new (Singleton(MyClass))();
const instance2 = new (Singleton(MyClass))();
console.log(instance1 === instance2); 

在这个示例中,使用 Proxy 拦截了对象的构造过程,当第一次创建对象时,会创建一个新实例并存储在 instance 属性中,后续再创建对象时,会直接返回已有的实例。