单例模式 介绍和举例

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

 

实现单例模式:

    var Singleton = function( name ) {
      this.name = name
    }

    Singleton.instance = null
    Singleton.prototype.getName = function() {
      console.log(this.name)
    }
    
    Singleton.getInstance = function(name) {
      if (!this.instance) {
        this.instance = new Singleton(name)
      }
      return this.instance
    }

    var a = Singleton.getInstance('one')
    var b = Singleton.getInstance('two')

    console.log(a === b)

用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一个获取该类的实例时,返回之前创建的对象。我们通过Singleton.getInstance来获取Singleton类唯一对象。这种方式相对简单,但是增加了这个类的“不透明性”。

 

透明的单例模式:

我们现在实现一个“透明”单例类,用户从这个类中创建对象的时候,可以像使用其他任何普通类一样。

    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 = Singleton.getInstance('one')
    var b = Singleton.getInstance('two')

    console.log(a === b)

虽然完成了透明单例类编写,但是使用了匿名函数和闭包,增加了程序复杂度,看起来也不舒服。

 

用代理实现单例模式:

    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)
    }

    var ProxySingletenCreateDiv = (function() {
      var instance
      return function(html) {
        if (!instance) {
          instance = new CreateDiv(html)
        }
        return instance
      }
    })()

    var a = new ProxySingletenCreateDiv('one')
    var b = new ProxySingletenCreateDiv('two')

    console.log(a === b)

通过引入代理类完成一个单例模式的编写,把负责管理单例的逻辑放到代理类ProxySingletenCreateDiv中。这样可以做到和普通类分离。

 

惰性单例:

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

此时我们还可以将单例逻辑从原代码中剥离出来,将这些逻辑封装在getSingle函数内部,创建对象的方法被单做参数传入getSingle函数:

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

用一个变量result来保存fn的计算结果,result在闭包中永远不会被销毁。在将来的请求中,如果result已被赋值,则直接返回这个值。

下面是一个创建唯一iframe用于动态加载第三方页面:

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

    var createSingleIframe = getSingle(function() {
      var iframe = document.createElement('iframe')
      document.body.appendChild(iframe)
      return iframe
    })

    document.getElementById('loginBtn').onclick = function() {
      var loginLayer = createSingleIframe()
      loginLayer.src = 'http://www.baidu.com'
    }

 

JavaScript中的单例模式:

单例模式的核心是确保只有一个实例,并提供全局访问。

全局变量不是单例模式,但是在js开发中,我们会把全局变量当作单例来用。

为了尽量减少全局变量污染可以使用以下两种方法进行优化:

  • 使用命名空间
    var namespace1 = {
      a: function() {
        alert(1)
      },
      b: function() {
        alert(2)
      }
    }
  • 使用闭包封装私有变量
    var user = (function() {
      var _name = 'aaa'
      var _age = 12

      return {
        getUserInfo: function() {
          return _name + '-' + _age
        }
      }

 

; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_Peripheral单例模式是一种常用的设计模式,它的主要作用是确保在整个应用程序DataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIF中,某个类只有一个实例存在并且可以被全局访问。下面是单例模式的几OMode = DMA_FIFOMode_Enable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.D个好处: 1. 节约系统资源:因为单例模式只创建一个对象实例,所以可以节约MA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst系统的资源消耗,避免不必要的内存分配。 2. 方便对对象实例的控制:_Single; DMA_Init(DMA1_Stream6, &DMA_InitStructure); //启动DMA传输 DMA_Cmd(DMA因为单例模式只有一个对象实例,所以可以方便地对这个实例进行控制管理1_Stream5, ENABLE); DMA_Cmd(DMA1_Stream6, ENABLE); } //I2S配置函数 void I2S。 3. 提高代码的复用性:因为单例模式只创建一个对象实例,所以可以在多_Configuration(void) { SPI_I2S_DeInit(SPI1); I2S_InitStructure.I2S_AudioFreq = 个地方重复使用这个实例,提高代码的复用性。 4. 简化系统的设计:因为44100; I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips; I2S_InitStructure.I单例模式只有一个对象实例,所以可以简化系统的设计,避免出现复杂的类层2S_DataFormat = I2S_DataFormat_16b; I2S_InitStructure.I2S_CPOL = I2S_CP次结构。 5. 方便进行参数配置:因为单例模式只有一个对象实例,所以可以方OL_Low; I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; I2S_InitStructure.I2S便地对这个实例进行参数配置,避免出现多个实例之间的参数冲突。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值