Skip to content

单例模式实现

描述

单例模式(Singleton Pattern)确保一个类只有一个实例,并提供一个全局访问点。

核心原理

  1. 构造函数私有化(禁止外部 new)
  2. 类内部创建唯一实例
  3. 提供全局访问方法

实现方式

1. 懒汉式(延迟加载)

js
class Singleton {
    constructor() {
        if (Singleton.instance) {
            return Singleton.instance;
        }
        Singleton.instance = this;
        this.data = [];
    }

    getData() {
        return this.data;
    }
}

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

2. 饿汉式(立即加载)

js
class Singleton {
    constructor() {
        this.data = [];
    }

    getData() {
        return this.data;
    }
}

Singleton.instance = new Singleton();

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

3. 闭包版(推荐)

js
class Singleton {
    constructor() {
        if (Singleton.instance) {
            return Singleton.instance;
        }
        this.data = [];
        Singleton.instance = this;
    }

    getData() {
        return this.data;
    }
}

// 或使用闭包实现私有变量
const Singleton = (function () {
    let instance;

    function createInstance() {
        const obj = new Object();
        obj.data = [];
        obj.getData = function () {
            return this.data;
        };
        return obj;
    }

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

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true

4. 代理模式版

js
class Singleton {
    constructor() {
        this.data = [];
    }
}

const ProxySingleton = (function () {
    let instance;

    return function () {
        if (!instance) {
            instance = new Singleton();
        }
        return instance;
    };
})();

const instance1 = new ProxySingleton();
const instance2 = new ProxySingleton();
console.log(instance1 === instance2); // true

5. ES6 符号版

js
const INSTANCE = Symbol("instance");

class Singleton {
    constructor() {
        if (!Singleton[INSTANCE]) {
            this.data = [];
            Singleton[INSTANCE] = this;
        }
        return Singleton[INSTANCE];
    }
}

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

实际应用

Redux Store(单例模式应用)

js
let store;

function createStore(reducer, initialState) {
    if (store) {
        throw new Error("A store already exists");
    }

    store = {
        state: initialState,
        listeners: [],

        getState() {
            return this.state;
        },

        dispatch(action) {
            this.state = reducer(this.state, action);
            this.listeners.forEach((listener) => listener());
        },

        subscribe(listener) {
            this.listeners.push(listener);
            return () => {
                this.listeners = this.listeners.filter((l) => l !== listener);
            };
        },
    };

    return store;
}

模态框管理

js
class ModalManager {
    constructor() {
        if (ModalManager.instance) {
            return ModalManager.instance;
        }

        this.modals = new Map();
        ModalManager.instance = this;
    }

    open(id, content) {
        if (this.modals.has(id)) {
            return this.modals.get(id);
        }

        const modal = this.createModal(content);
        this.modals.set(id, modal);
        return modal;
    }

    close(id) {
        if (this.modals.has(id)) {
            this.modals.get(id).remove();
            this.modals.delete(id);
        }
    }

    createModal(content) {
        const modal = document.createElement("div");
        modal.innerHTML = content;
        document.body.appendChild(modal);
        return modal;
    }
}

const modalManager = new ModalManager();

单例 vs 静态类

特性单例模式静态类
实例化延迟/立即不可实例化
继承可继承、多态不可继承
实现方式类实例类本身
内存单一实例按需加载
线程安全需要处理自动安全