设计模式-单例模式

107 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情

什么是单例模式

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

比如 redux 中的 store,线程池,全局缓存,浏览器 window 对象等。

实现一个单例模式

实现:通过一个变量来标记是否为某个类创建过对象,如果创建过则在下次创建的时候直接返回之前创建的对象

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

class Person {
  constructor(name) {
    this.name = name;
    this.init();
  }
  init() {
    this.age = 18;
  }
}

// 代理实现单例模式
const ProxySingletonPerson = (function () {
  var instance;
  return function (name) {
    // 缓存代理
    if (!instance) {
      instance = new Person(name);
    }
    return instance;
  };
})();

const p1 = new ProxySingletonPerson('xx');
const p2 = new ProxySingletonPerson('cd');
// p1:  Person {name: 'xx', age: 18}
// p2:  Person {name: 'xx', age: 18}
p1 === p2; // true

可以看到 p1p2 返回的都是第一次 new 的那个实例( p1 ),说明他是惰性的

通用的惰性单例

let getSingle = function (fn) {
  let result;
  return function () {
    if (!result) {
      result = fn.apply(this, arguments);
    }
    return result;
    // or
    // return result || ( result = fn .apply(this, arguments ) );
  };
};

我们在看个例子:

const createLogin = function () {
  var div = document.createElement('div');
  div.innerHTML = 'this is login';
  div.id = 'loginBtn';
  document.body.appendChild(div);
  return div;
};
const createIframe = function () {
  var iframe = document.createElement('iframe');
  document.body.appendChild(iframe);
  return iframe;
};

// 在页面创建登录按钮
const loginDom = getSingle(createLogin());
// 创建一个 iframe 单例
const iframe = getSingle(createIframe);

// 点击登录按钮,通过 iframe 加载第三方页面
document.getElementById('loginBtn').onclick = function () {
  var loginLayer = iframe();
  loginLayer.src = 'https://wuxiaobai.cn';
};

总结

getSinge 函数中,实际上也提到了闭包和高阶函数的概念。

单例模式是一种简单但非常实用的模式,特别是惰性单例技术,在合适的时候才创建对象,并且只创建唯一的一个,这对于我们队页面的优化也是有一些帮助,比如懒加载。