常用且实用的设计模式——单例模式

177 阅读1分钟

这是我参与更文挑战的第16天,活动详情查看:更文挑战

单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式是一个常用的模式,有些对象我们往往只需要一个,比如线程池,全局缓存等等。

一个简单的单例模式例子

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

Singleton.prototype.getName = function() {
  return this.name;
};

Singleton.getInstance = (function() {
  var instance = null;
  return function(name) {
    if (!instance) {
      this.instance = new Singleton(name);
    }
    return instance;
  };
})();

var a = Singleton.getInstance("bob1");
var b = Singleton.getInstance("bob2");

console.log(a === b);  // true

这里创建了一个Singleton类,当我们去创建这个类的实例的时候,始终只返回一个实例。但是这样写会让用这个类的人感到困惑,每次创建实例都需要用Singleton.getInstance方法,这样不符合我们日常创建实例的习惯,所以要稍微改造一下。

代理方式实现的单例模式

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>
  <body>
    <script>
      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 ProxySingletonCreateDiv = (function() {
        var instance;
        return function(html) {
          if (!instance) {
            instance = new CreateDiv(html);
          }
          return instance;
        };
      })();

      var a = new ProxySingletonCreateDiv("bob1");
      var b = new ProxySingletonCreateDiv("bob2");

      console.log(a === b); // true
    </script>
  </body>
</html>

这里我们用了ProxySingletonCreateDiv这个代理函数,来实现创建单例模式的类,通过这个这个方法创建的实例都是单例模式的产物。

通用的惰性单例

惰性单例指的是惰性生成实例的意思。只有在我们调用具体方法的时候才会去生成实例。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 通用的单例模式
      // 只用在调用getSingle的时候才会生成实例
      // 分离实现单例和类的实现方法,便于管理
      var getSingle = function (fn) {
        var result;
        return function () {
          return result || (result = fn.apply(this, arguments));
        };
      };

      var CreateLoginLayer = function () {
        var div = document.createElement("div");
        div.innerHTML = "loginLayer";
        div.style.display = "none";
        document.body.appendChild(div);
        return div;
      };

      var createSingleLoginLayer = getSingle(CreateLoginLayer);

      var a = CreateLoginLayer();
      var b = CreateLoginLayer();
      var e = createSingleLoginLayer();
      var f = createSingleLoginLayer();

      console.log(a === b); // false
      console.log(e === f); // true
    </script>
  </body>
</html>

引用

[1] 曾探:JavaScript设计模式与开发实践