单例模式,适用于对象唯一的情景(设计模式与开发实践 P4)

文章目录

上一章后续的内容是关于 JS 函数闭包的,考虑很多读者已经有了闭包基础或者希望通过实战理解,遂跳过上一章直接开始设计模式篇~

需要注意的是,代码部分仅供参考,主要关注的内容是设计模式的思想和运用,结合到自己的实战中才是最好的

单例模式

单例模式的定义是:保证一个类只有一个实例,并提供一个访问他的全局访问点

例如:线程池,全局缓存,登陆窗口(无论你点击多少次,窗口都只会创建一个)

实现

实现起来并不复杂,只需要创建一个变量来标识是否已经为某个类创建过对象,如果已经创建了,那就直接返回之前创建的对象~

javascript 复制代码
const Singleton = {
  instance: null,
  getInstance: function () {
    if (!this.instance) {
      this.instance = {
        // 在这里定义单例的属性和方法
        name: "Singleton Instance",
        sayHello: function () {
          console.log("Hello from Singleton!");
        },
      };
    }
    return this.instance;
  },
};

// 使用示例
const instance1 = Singleton.getInstance();
console.log(instance1.name); // 输出: Singleton Instance
instance1.sayHello(); // 输出: Hello from Singleton!

const instance2 = Singleton.getInstance();
console.log(instance2.name); // 输出: Singleton Instance

console.log(instance1 === instance2); // 输出: true

方便结合理解,我们加入一个静态型面向对象的语言 C# 来看:

csharp 复制代码
public class Singleton
{
    private static Singleton instance;

    // 私有构造函数,防止外部实例化
    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }

    // 在这里定义单例的其他属性和方法
    public string Name { get; set; }

    public void SayHello()
    {
        Console.WriteLine("Hello from Singleton!");
    }
}

代理单例

上面的代码有一个问题,你会发现 JS 部分中,一部分代码用来保证单例不重复创建,另一部分代码用来创建单例对象,显然这不是一个好的做法,如果某一天我们要改写这个单例代码,无疑会使代码变得复杂,所以引入 代理 单例模式

通过这样就使得 Singleton 成为了一个普通的类,和 Proxy 组成了单例模式!

javascript 复制代码
var Singleton = function () {
  this.name = "Singleton Instance";
};

Singleton.prototype.sayHello = function () {
  console.log("Hello from Singleton!");
};

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

// 使用示例
var proxyInstance1 = new SingletonProxy();
var proxyInstance2 = new SingletonProxy();

console.log(proxyInstance1.name);
console.log(proxyInstance2.name);

同样还有 C# 版的:

csharp 复制代码
private class Singleton
{
    private Singleton()
    {
        // 构造函数
    }
}

public class SingletonProxy
{
    private Singleton proxyInstance;
    
    public Singleton GetInstance()
    {
        if (proxyInstance == null)
        {
            proxyInstance = Singleton.Instance;
        }
        return proxyInstance;
    }
}

惰性单例

上面的代码已经实现了惰性单例模式:只有调用的时候才实现对象的初始化,即这一段:

csharp 复制代码
public Singleton GetInstance()
{
    if (proxyInstance == null)
    {
        proxyInstance = Singleton.Instance;
    }
    return proxyInstance;
}

这样使得资源和配置更灵活,且线程安全~

相关推荐
workflower4 小时前
装备企业的 AI 路线图
人工智能·深度学习·机器学习·设计模式·机器人
用户938515635077 小时前
从零构建《天龙八部》知识库:EPUB 加载→文本分割→向量嵌入→Milvus 存储→RAG 问答,一条链路打通
javascript·人工智能·全栈
柚yuzumi9 小时前
变量明明定义了,为什么访问不到?深入理解 JavaScript 作用域
javascript
何时梦醒9 小时前
React + TypeScript + Vite 实战:从零构建 Color Picker 应用
前端·javascript·架构
Highcharts.js9 小时前
基于Highcharts开发的OHLC 股票K线图完全指南
javascript·信息可视化·echarts·数据可视化·highcharts·ohlc
默_笙9 小时前
😋 我让 DeepSeek-R1 在浏览器本地跑了起来,后端同事说"你认真的?"
前端·javascript
JasonMa15311 小时前
从零搭建一个微信小程序活动管理平台(一):架构设计与技术选型
javascript·微信小程序·node.js
sugar__salt12 小时前
Vue3 核心特性深度解析:v-model、ref 属性与 nextTick 完全指南
前端·javascript·vue.js·前端框架·vue
古韵12 小时前
你的 uni-app 分页,一个 hook 搞定竞态和加载
javascript·vue.js·uni-app
成都渲染101云渲染666613 小时前
Blender渲染时,纯CPU渲染的设置教程
前端·javascript·blender