说说你对单例模式的理解

157 阅读3分钟

单例模式是什么?

创建型模式,提供了一种创建对象的最佳方式,这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。在应用程序运行期间,单例模式只会在全局作用域下创建一次实例对象,让所有需要调用的地方都共享这一单例对象。

从定义上来看,全局变量好像就是单例模式,但是一般情况我们不认为全局变量是一个单例模式,原因是:

  • 全局命名污染
  • 不易维护,容易被重写覆盖

单例模式如何实现?

ES5

var singleton = (function() {
  var instance;

  function init() {
    // 单例代码
    return {
      // 公共方法和变量
      publicMethod: function() {
        console.log("Hello World!");
      },
      publicProperty: "test"
    };
  }

  return {
    // 获取单例实例的方法
    getInstance: function() {
      if (!instance) {
        instance = init();
      }
      return instance;
    }
  };
})();

// 使用单例
var mySingleton = singleton.getInstance();
mySingleton.publicMethod();


ES6

class Singleton {
  constructor() {
    if (!Singleton.instance) {
      // 单例代码
      Singleton.instance = this;
    }
    return Singleton.instance;
  }
  // 公共方法和变量
  publicMethod() {
    console.log("Hello World!");
  }
  publicProperty = "test";
}

// 使用单例
const mySingleton = new Singleton();
mySingleton.publicMethod();

闭包

const singleton = (function() {
  let instance;

  function init() {
    // 单例代码
    return {
      // 公共方法和变量
      publicMethod: function() {
        console.log("Hello World!");
      },
      publicProperty: "test"
    };
  }

  return {
    // 获取单例实例的方法
    getInstance: function() {
      if (!instance) {
        instance = init();
      }
      return instance;
    }
  };
})();

// 使用单例
const mySingleton = singleton.getInstance();
mySingleton.publicMethod();

单例模式的应用场景?

在前端中,很多情况都是用到单例模式

应用实例

  • 例如页面存在一个模态框的时候

    只有用户点击的时候才会创建,而不是加载完成之后再创建弹窗和隐藏,并且保证弹窗全局只有一个。

  • Vuexredux全局态管理库也应用单例模式的思想

image.png

  • 现在很多第三方库都是单例模式,多次引用只会使用同一个对象,如jquerylodashmoment...

  • 有一些对象往往只需要有一个,比如线程池、全局缓存浏览器中的Windows对象等

项目实战

  • 例如页面存在一个模态框

这种实现称为惰性单例,意图是只有当需要时才创建类实例对象

可以先创建一个通常的获取对象的方法,如下:

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

创建弹窗的代码如下:

const createLoginLayer = function(){
  var div = document.createElement( 'div' );
  div.innerHTML = '我是浮窗';
  div.style.display = 'none';
  document.body.appendChild( div );
  return div;
}; 

const createSingleLoginLayer = getSingle( createLoginLayer ); 

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

总结

单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。

优缺点

优点:

  • 适用于单一对象,只生成一个对象实例,避免频繁创建和销毁实例,减少内存占用。

缺点:

  • 不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
  • 由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
  • 单例类的职责过重,在一定程度上违背了“单一职责原则”。


最后一句
学习心得!若有不正,还望斧正。希望掘友们不要吝啬对我的建议。