JavaScript单例模式的三种实现

发布时间:2023年12月28日

单例模式

????????单例模式是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。

实现单例

方式一?

      //创建单例
      class SingleTon {
        //添加静态私有属性
        static #instanse;
        //添加静态方法
        static getInstanse() {
          //判断静态私有属性内是否有实例,如果没有就创建一个并返回,如果有就直接返回
          if (this.#instanse === undefined) {
            this.#instanse = new SingleTon();
          }
          return this.#instanse;
        }
      }

      const sing1 = SingleTon.getInstanse();
      const sing2 = SingleTon.getInstanse();
      console.log(sing1 === sing2);    //true

最简单的方式就是希望别人通过 SingleTon.getInstanse()的方式来获得一个实例。但是这种方法不能保证别人不去new一个,这样就不能保证单例了

      const sing1 = SingleTon.getInstanse();
      const sing2 = new SingleTon();
      console.log(sing1 === sing2); //false

?方式二

ES6新增了模块化,那我直接导出创建的实例,不就能解决问题了吗?我们来看看是否能达到目的。?

//创建单例
class SingleTon {
    //添加静态私有属性
    static #instanse;
    //添加静态方法
    static getInstanse() {
        //判断静态私有属性内是否有实例,如果没有就创建一个并返回,如果有就直接返回
        if (this.#instanse === undefined) {
            this.#instanse = new SingleTon();
        }
        return this.#instanse;
    }
}
export default SingleTon.getInstanse();

看起来好像没什么问题,但此处还存在隐患,导出的实例对象可以通过?constructor找到其构造函数,构造函数都找到了,不也可以直接new一个新的实例化对象吗?

    <script type="module">
      import v from "./SingleTon.js";
      const v2 = new v.constructor();
      console.log(v2 === v);    //false
    </script>

方式三?

通过代理实现单例?

      //创建单例
      class SingleTon {
        //添加静态私有属性
        static #instanse;
        //添加静态方法
        static getInstanse() {
          //判断静态私有属性内是否有实例,如果没有就创建一个并返回,如果有就直接返回
          if (this.#instanse === undefined) {
            this.#instanse = new SingleTon();
          }
          return this.#instanse;
        }
      }

      //传入一个构造函数,返回一个代理
      function SingleTonfn(targetConstructor) {
        let ins = null;
        const proxy = new Proxy(targetConstructor, {
          construct(target, args) {
            if (!ins) ins = new targetConstructor(...args);
            return ins;
          },
        });
        targetConstructor.prototype.constructor = proxy;    //将其原型的指向 指为proxy
        return proxy;
      }

      const v = SingleTonfn(SingleTon);
      const v1 = new v();
      const v2 = new v();
      const v3 = new v1.constructor();
      console.log(v1 === v2);    //true
      console.log(v1 === v3);    //true

文章来源:https://blog.csdn.net/m0_53062068/article/details/135206962
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。