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


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

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

    单例模式

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

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

    实现

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

    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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

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

    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!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    代理单例

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

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

    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    同样还有 C# 版的:

    private class Singleton
    {
        private Singleton()
        {
            // 构造函数
        }
    }
    
    public class SingletonProxy
    {
        private Singleton proxyInstance;
        
        public Singleton GetInstance()
        {
            if (proxyInstance == null)
            {
                proxyInstance = Singleton.Instance;
            }
            return proxyInstance;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    惰性单例

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

    public Singleton GetInstance()
    {
        if (proxyInstance == null)
        {
            proxyInstance = Singleton.Instance;
        }
        return proxyInstance;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

  • 相关阅读:
    【C++初阶】前言——C++的发展简述及学习方法分享
    Django视图层解析
    使用机器学习进行客户终身价值和RFM模型分析
    C#开发的OpenRA游戏之世界存在的属性RenderDebugState(5)
    业务架构·应用架构·数据架构实战~战略驱动的业务架构设计
    【Python刷题篇】——Python入门 09 字典(上)
    基于Spark的大规模日志分析
    java程序员都应该知道的Java 截取字符串的几种操作
    js数据类型、节流/防抖、点击事件委派优化、过渡动画
    如何解决多人编辑场景下的内容覆盖问题
  • 原文地址:https://blog.csdn.net/Littlelumos/article/details/132893538