定义

单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。

特点

  1. 某个类只能有一个实例
  2. 它必须自行创建这个实例
  3. 它必须自行向整个系统提供这个实例

适用场景

  1. 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器,或者需要考虑资源消耗太大而只允许创建一个对象
  2. 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。
  3. 在一个系统中要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就需要对单例模式进行改进,使之成为多例模式

优点

  1. 提供了对唯一实例的受控访问并可以节约系统资源
  2. 设置全局访问点,优化和共享资源访问,减少内存开支

缺点

  1. 缺点在于因为缺少抽象层而难以扩展,且单例类职责过重

javscript实现

var SingletonTester = (function () {

  //参数:传递给单例的一个参数集合
  function Singleton(args) {
    //设置args变量为接收的参数或者为空(如果没有提供的话)
    var args = args || {}
    //设置name参数
    this.name = 'SingletonTester'
    //设置pointX的值
    this.pointX = args.pointX || 6 //从接收的参数里获取,或者设置为默认值
    //设置pointY的值
    this.pointY = args.pointY || 10
  }

  //实例容器
  var instance
  var _static = {
    name: 'SingletonTester',
    //获取实例的方法
    //返回Singleton的实例
    getInstance: function (args) {
      if (instance === undefined) {
        instance = new Singleton(args)
      }
      return instance
    }
  }
  return _static
})();
var singletonTest = SingletonTester.getInstance({pointX: 5})
console.log(singletonTest.pointX) // 输出 5

更多实现方式

方法1:

function Universe() {
  // 判断是否存在实例
  if (typeof Universe.instance === 'object') {
    return Universe.instance
  }
  // 其它内容
  this.start_time = 0
  this.bang = "Big"
  // 缓存
  Universe.instance = this
  // 隐式返回this
}
// 测试
var uni = new Universe()
var uni2 = new Universe()
console.log(uni === uni2) // true

方法2:

function Universe() {
  // 缓存的实例
  var instance = this
  // 其它内容
  this.start_time = 0
  this.bang = "Big"
  // 重写构造函数
  Universe = function () {
    return instance
  }
}
// 测试
var uni = new Universe()
var uni2 = new Universe()
uni.bang = "123"
console.log(uni === uni2) // true
console.log(uni2.bang) // 123