单例模式,适用于对象唯一的情景(设计模式与开发实践 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;
}

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

相关推荐
努力往上爬de蜗牛1 小时前
react native真机调试
javascript·react native·react.js
y***86692 小时前
TypeScript在Electron应用中的使用
javascript·typescript·electron
zy happy4 小时前
若依 vue3 报错:找不到模块“@/api/xxxx/xxxxx”或其相应的类型声明。。Vue 3 can not find mod
前端·javascript·vue.js
meichaoWen5 小时前
【Vue3】vue3的全面学习(一)
前端·javascript·学习
在未来等你5 小时前
AI Agent设计模式 Day 19:Feedback-Loop模式:反馈循环与自我优化
设计模式·llm·react·ai agent·plan-and-execute
b***74887 小时前
Vue开源
前端·javascript·vue.js
ByteCraze8 小时前
我整理的大文件上传方案设计
前端·javascript
前端小白۞8 小时前
vue2 md文件预览和下载
前端·javascript·vue.js
5***79009 小时前
Vue项目性能优化
前端·javascript·vue.js
丫丫72373410 小时前
Three.js 模型树结构与节点查询学习笔记
javascript·webgl