• js 设计模式——单例模式


    单例模式

    保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的 window 对象等。

    JavaScript 中的单例模式

    1. 使用命名空间

    在JavaScript里,实现单例的方式有很多种,其中最简单的一个方式是使用对象字面量的方法,其字面量里可以包含大量的属性和方法:

    let people = {
      name: "Jack",
      age: 18,
      play() {
        console.log('i like game');
      }
    }
    

    还可以动态地创建命名空间

    // 定义对象
    var MyApp = {};
    // 对象的方法
    MyApp.namespace = function( name ){
      // 将参数分割成数组
      var parts = name.split( '.' );
      // 定义变量
      var current = MyApp;
      // 创建对象里面的属性
      for ( var i in parts ){
        if ( !current[ parts[ i ] ] ){
          current[ parts[ i ] ] = {};
        }
        current = current[ parts[ i ] ];
      }
    };
    MyApp.namespace( 'event' );
    MyApp.namespace( 'dom.style' );
    
    /******************* 上面没看懂没关系 ***********************/
    // 上述代码等价于
    var MyApp = {
      event: {},
      dom: {
        style: {}
      } 
    };
    

    2. 使用闭包封装私有变量

    var user = (function(){ 
      var __name = 'sven', 
      __age = 29; 
      return { 
        getUserInfo: function(){ 
          return __name + '-' + __age; 
        } 
      } 
    })();
    

    我们用下划线来约定私有变量 __name__age ,它们被封装在闭包产生的作用域中,外部是访问不到这两个变量的,这就避免了对全局的命令污染。


    实现一个标准的单例模式

    var Singleton = function( name ){
      this.name = name;
      this.instance = null;
    };
    Singleton.prototype.getName = function(){
      alert ( this.name );
    };
    Singleton.getInstance = function( name ){
      if ( !this.instance ){
        this.instance = new Singleton( name );
      }
      return this.instance;
    };
    var a = Singleton.getInstance( 'sven1' );
    var b = Singleton.getInstance( 'sven2' );
    alert ( a === b ); // true
    

    我们通过 Singleton.getInstance 来获取 Singleton 类的唯一对象,这种方式相对简单,但有一个问题,就是增加了这个类的“不透明性”, Singleton 类的使用者必须知道这是一个单例类,跟以往通过 new XXX 的方式来获取对象不同,这里偏要使用 Singleton.getInstance 来获取对象。

    透明的单例模式

    var CreateDiv = (function(){
      var instance;
      var CreateDiv = function( html ){
        if ( instance ){
          return instance;
        }
        this.html = html;
        this.init();
        return instance = this;
      };
      CreateDiv.prototype.init = function(){
        var div = document.createElement( 'div' );
        div.innerHTML = this.html;
        document.body.appendChild( div );
      };
      return CreateDiv;
    })();
    var a = new CreateDiv( 'sven1' );
    var b = new CreateDiv( 'sven2' );
    alert ( a === b ); // true
    

    为了把 instance 封装起来,我们使用了自执行的匿名函数和闭包,并且让这个匿名函数返回
    真正的 Singleton 构造方法,这增加了一些程序的复杂度

    3. 用代理实现单例模式

    var CreateDiv = function( html ){
      this.html = html;
      this.init();
    };
    CreateDiv.prototype.init = function(){
      var div = document.createElement( 'div' );
      div.innerHTML = this.html;
      document.body.appendChild( div );
    };
    // 代理类 proxySingletonCreateDiv:
    var ProxySingletonCreateDiv = (function(){
      var instance;
      return function( html ){
        if ( !instance ){
          instance = new CreateDiv( html );
        }
        return instance;
      }
    })();
    var a = new ProxySingletonCreateDiv( 'sven1' );
    var b = new ProxySingletonCreateDiv( 'sven2' );
    alert ( a === b );
    

    通过引入代理类的方式,我们同样完成了一个单例模式的编写,跟之前不同的是,现在我们
    把负责管理单例的逻辑移到了代理类 proxySingletonCreateDiv 中。这样一来,CreateDiv 就变成了一个普通的类,它跟 proxySingletonCreateDiv 组合起来可以达到单例模式的效果。

    惰性单例

    惰性单例指的是在需要的时候才创建对象实例。

    var Singleton = (function () {
      var instantiated;
      function init() {
        /*这里定义单例代码*/
        return {
          publicMethod: function () {
          console.log('hello world');
        },
        publicProperty: 'test'
      };
    }
    
    return {
      getInstance: function () {
        if (!instantiated) {
          instantiated = init();
        }
        return instantiated;
      }
    };
    })();
    
    /*调用公有的方法来获取实例:*/
    Singleton.getInstance().publicMethod(); 
    

    通过以上方法我们就可以做到只有在使用的时候才初始化,从而达到节约资源的目的

    目前对于单例模式的理解就这么多,以后有了新的理解会继续更新的,溜了溜了(~ ̄▽ ̄)~

  • 相关阅读:
    .net 平台 统计图表展示控件fusioncharts
    sql 查分数段人数
    小程序开发之填坑之路
    提高网站性能
    javascript History对象详解
    vue的双向数据绑定
    静态文件对加快文件加载速度的影响
    JavaScript代码异常监控
    BEM命名规则
    浏览器缓存
  • 原文地址:https://www.cnblogs.com/loveyt/p/11413474.html
Copyright © 2020-2023  润新知