前端设计模式-单例模式

前言

概念: 确保一个类只有一个实例,并提供一个全局访问点来访问该实例。

使用场景:如vue的状态管理工具vuex

好处:符合路径唯一型和错误提示型两种开发规范,减少开发错误

实现方式:

ts版本

我们通过private关键字使这个类不能在外部new,否则报错。我们定义了一个方法获取这个实例,通过判断这个实例的存在来保证唯一性

typescript 复制代码
class Singleton {
    private static instance: Singleton;
    private constructor() { }
    // 通过静态方法获取实例
    public static getInstance() {
        if (!this.instance) {
            this.instance = new Singleton();
        }
        return this.instance;
    }
    public someBusinessLogic() {
        // ...
    }
}

// 直接new会报错
new Singleton(); // error:Constructor of class 'Singleton' is private and only accessible within the class declaration

// 通过定义的getInstance方法
console.log(Singleton.getInstance() === Singleton.getInstance()) // true,说明只创建了一个实例

js版本

版本1

好处:使用模块化避免内部直接new和通过静态方法new造成的不同实例产生

缺陷:存在通过原型的contructor函数重复new的隐患

javascript 复制代码
// single.js
class Singleton {
    constructor() {}
    static _instance;
    static getInstance() {
        if (!this._instance) {
            this._instance = new Singleton();
        }
        return this._instance;
    }
}
export default Singleton.getInstance();
​
// test.js
import stance from './single.js';
const a = new stance.constructor();
const b = new stance.constructor();
console.log(a === b); // false

我们通过模块化的方式直接导出类的getInstance方法,这里可以隐藏了这个类,别处使用的唯一实例,但是别人可能通过constructor(指向的就是这个类)取执行new,那么就绕过了我们写的判断

版本2(使用proxy完美保证单例模式)

javascript 复制代码
class Singleton {
    constructor() {}
}

// 封装一个函数,传入一个类,返回一个新的代理单例类
function toProxySingleton(className) {
    let instance;
    const proxyClass = new Proxy(className, {
        // 如果通过new调用,就会触发construct方法
        // 第一个参数是目标类,第二个参数是类里面的contructor的参数
        construct(target, argumentsList) {
            if (!instance) {
                console.log('new');
                instance = new className(...argumentsList);
                // 也可以通过Reflect.construct来创建实例
                // instance = Reflect.construct(target, argumentsList);
            } else {
                console.warn('instance already exists');
            }
            return instance;
        }
    });
    className.prototype.constructor = proxyClass; // 修复constructor指向
    return proxyClass;
}

const ProxySingle = toProxySingleton(Singleton);
console.log(new proxySingle() === new proxySingle()); // true,说明只创建了一个实例
console.log(new proxySingle() === new Singleton.constructor()) // true 使用contructor也不能创建第二个实例了
export default ProxySingle;

这时候我们在外部使用只需要引入这一个类去new即可,始终保证了一个类的实例的单一性

提醒:上述ts使用private实现的单例模式只能给我们语法上的提示,在编译为js的时候,js文件是没有报错效果的,仍然可以创造多个不同实例.

相关推荐
码匠许师傅4 小时前
【设计模式精讲】4.单例模式(Singleton)
c++·单例模式·设计模式
雾削木4 小时前
2026 编程领域热点知识速览:AI 辅助开发、设计模式实战与嵌入式高效迭代
人工智能·设计模式
AI人工智能+电脑小能手1 天前
大白话说Java设计模式-42-访问者模式(业务实战篇)
java·spring·设计模式·访问者模式·asm·营销规则·数据结构与操作分离
AI人工智能+电脑小能手1 天前
大白话说Java设计模式-43-访问者模式(源码剖析篇)
java·设计模式·访问者模式·源码分析·elementvisitor·asm classvisitor·spring spel
Michael_lcf2 天前
Agent设计模式:思考-行动-观察循环的本质与局限
设计模式·agent设计模式·agent设计模式的本质
丰锋ff2 天前
设计模式学习笔记
笔记·学习·设计模式
米啦啦.2 天前
设计模式/
观察者模式·单例模式·设计模式·工厂模式
QuZhengRong2 天前
【AI】Agent 全栈进阶|Agent 设计模式
人工智能·学习·设计模式·llm·agent
码匠许师傅2 天前
【设计模式精讲】2. 设计原则基石:SOLID 与几条关键原则
java·设计模式·log4j
AI人工智能+电脑小能手2 天前
大白话说Java设计模式-41-备忘录模式(源码剖析篇)
java·设计模式·备忘录模式·源码分析·serializable·undo log·spring statemachine