JavaScript单例模式能不能去实例只留单原理解析

2022-12-23 11:04:49
目录
一、单例模式的分类二、惰性单例模式二、普通单例模式总结

一、单例模式的分类

一个环境中有且只有一个实例,并且当前环境可以访问到它。往小了说,当前环境可以是一个函数作用域、块级作用域,往大了说可以是全局window或者global环境。如果按照实例的创建时机进行单例模式的分类,有:

    普通单例模式:在环境初始时就创建惰性单例模式:在某个特定的时机才创建

    二、惰性单例模式

    从单例模式的定义出发,一个环境中有且只有一个实例,并且使用时才去创建它,那么就可以把当前单例模式称之为惰性单例模式

      惰性,指的是只有在使用的时候才去创建单例,指的是当前环境有且只有单一的一个实例

      弹窗案例:在页面打开的时候,页面中有登录按钮,在点击时,需要创建一个dom节点。
      (1)首先,实现一个功能函数:创建节点的函数

      var domFun = function () {
          var dom = document.createElement('div');
          dom.innerHTML = '登录窗口demo'
          dom.style.display = 'none';
          document.body.appendChild(dom);
          return dom;
      }
      

      (2)其次,创建管理单例的函数

      var createSingle = function (fn) {
          var result;
          return function () {
              return result || (result = fn.apply(this, arguments));
          }
      }
      

      采用闭包的形式,让result变量在当前环境不销毁,如果该变量已经存在,直接返回,如果没有,让当前环境调用fn功能函数,并赋值给result。该过程保证了当前环境只有一个实例。
      (3)将创建节点的函数和管理单例的函数糅合

      var createSingleDom = createSingle(domFun)
      

      (4)最后,在点击按钮的时候,进行实例的创建

      var loginBtn = document.querySelector('.login')
      loginBtn.onclick = function () {
          var loginDom = createSingleDom()
          console.log(loginDom)
          loginDom.style.display = 'block'
      }
      

      该过程实现了只有在点击登录按钮的时候才创建节点,是惰性的。

      整个过程,将创建惰性实例的过程进行了分解,更易于修改和维护,如果,创建的不是div节点,而是,image图片、iframe嵌套网页、倒计时等其他内容,只需要替换步骤(1)中的内容即可。

      这里的例子,我们严格的强调一个实例的事儿。

      二、普通单例模式

      在vue中的应用:我们知道vue是一个渐进式框架,主要实现视图的渲染,其他的功能可以可以通过第三方插件按需引入,比如路由插件vue-router和全局状态管理vuex

        路由vue-router的使用
        import Vue from "vue";
        import VueRouter from "vue-router";
        Vue.use(VueRouter);
        
          状态vuex的使用
          import Vue from "vue";
          import Vuex from "vuex";
          Vue.use(Vuex);
          

          vue通过Vue.use(Vuex)的方式进行vue-routervuex的安装,Vue.use的代码如下:

          Vue.use = function (plugin: Function | Object) {
              const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
              if (installedPlugins.indexOf(plugin) > -1) {
                return this
              }
              // 去掉参数列表中的第一个
              const args = toArray(arguments, 1)
              // 将Vue作为this推入到参数的首位
              args.unshift(this)
              if (typeof plugin.install === 'function') {
                plugin.install.apply(plugin, args)
              } else if (typeof plugin === 'function') {
                plugin.apply(null, args)
              }
              installedPlugins.push(plugin)
              return this
          }
          

          可以看出,首次执行vue.use(xxx)的时候,会将该插件推入到数组installedPlugins中去,再次执行vue.use(xxx)的时候,installedPlugins.indexOf(plugin) > -1true,则终止后续逻辑的执行。也就说,vue.use(xxx)只会让该插件执行一次install的安装。

          再看 const installedPlugins = (this._installedPlugins || (this._installedPlugins = [])),是不是发现,这里也是单例模式的影子,当this._installedPlugins不存在时为其赋值为[],当前存在时直接返回。

          单例模式,去掉具体的例,就剩单模式。就像当前例子中,install只执行一次,this._installedPlugins只初始化一次一样,就体现了一个单字。那这算不算单(例)模式呢?

          总结

          单例模式是不是可以去实例,只留单呢?这样,很多只执行一次的逻辑也就和单例模式能搭上关系了。仁者见仁智者见智,能不能去,纯属个人想法。因为,优秀的单例模式,是经过无数的程序案例得出的经验性汇总。

          以上就是JavaScript单例模式能不能去实例只留单原理解析的详细内容,更多关于JavaScript单例模式去实例的资料请关注易采站长站其它相关文章!