基本概念

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

单例的实现

传统语言描述的单例模式JavaScript实现

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('seven1');
var b = SingleTon.getInstance('seven2');

JavaScript的单例模式实现

实现原理:利用闭包来保持对一个局部变量的引用,这个变量保存着首次创建的唯一的实例

SingleTon.getSingle = (function(){
    var instance = null;
  return function(name){
    if(!instance){
      instance = new SingleTon(name);
    }
    return instance;
  }
})(); 

单例的运用

惰性单例模式

只在需要的时候才创建该单例

var SingleTon = function(foo){
  var instance = null;
  return function(){
    return instance || (instance = foo.apply(this,arguments));
  }
}; 

var createLoginLayer=(function(){
  var div;
  return function(){
    if(!div){
      div=document.createElement('div');    //创建一个登录框
    }
      return div;
  }
})();

document.getElementById('loginBtn').onclick=function(){
  var loginLayer=createLoginLayer();
  loginLayer.style.display='block';
};

当用户第一次点击登录按钮时,来创建并显示登录窗口,之后重复点击按钮不会重复创建

缓存函数的计算结果

以下是不缓存的写法,非常慢!

function foo(n){
  results = n < 2 ? n : foo(n - 1) + foo(n - 2);
  return results;
}
console.log(foo(40)); //得计算好几秒 

以下是缓存写法,基本瞬间出结果!

var foo = (function(){
var cache = {};
return function(n){
  if(!cache[n]){
    cache[n] = n < 2 ? n : foo(n - 1) + foo(n - 2);
  }
  return cache[n];
};
})();
console.log(foo(100));

命名空间

单例模式可以提供一个命名空间,例如jQuery库的命名空间为jQuery或$。命名空间的使用是为了让代码更加整洁,在多人协作开发的情况下,不同的人定义的变量很有可能重复,此时就需要使用命名空间来约束每个人定义的变量,使相同名称的变量放在不同的命名空间中,避免相互干扰

// A程序员的命名空间
var A = {
  get: function(id){
    return document.getElementById(id);
  }
  css: function(id,key,value){
    get(id).style[key] = value;
  }
}
// B程序员的命名空间
var B = {
  get: function(className){
    return document.getElementByClassName(className)[0];
  }
  css: function(className,key,value){
    get(className).style[key] = value;
  }
}

A、B两个命名空间中都有一个get方法和一个css方法,用于元素获取和元素样式修改,不同的是A是通过id来获取元素,而B是通过class来获取元素,通过命名空间,可以使这些相同名称的方法共存,使用时指定相应的命名空间即可。

单例的优点与缺点

优点

单例模式声明一个命名空间,它生成一个唯一的全局变量

在实现同一个功能的地方比通过new新创建对象对内存对资源的占用更据优势

缺点

它的扩展性不好,对一个单例对象里面的方法重写时会破坏原有的需求

灵活性不好, 当某个需要实现该功能的需求需要变动时,而其他的又不需要变动时,单例对象就不好处理了