设计模式-单例模式

单例模式的定义:保证一个类仅有一个实例,并能够被全局访问。

单例模式在开发中应用非常广泛,比如网站的登录浮窗,当我们单击登录按钮的时候,页面中会出现一个登录浮窗,这个登录浮窗是唯一的,无论单击多少次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗就适合用单例模式来创建

单例模式

下面使用单例模式创建一个DIV节点

// 用于创建DIV的类
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) {
    return instance || (instance = new CreateDiv(html));
  }
})();

// 测试
var a = new ProxySingletonCreateDiv('sven1');
var b = new ProxySingletonCreateDiv('sven2');
console.log(a == b) // true

无论实例化多少个ProxySingletonCreateDiv,最终都只创建一个div,这就是单例模式。CreateDiv用于实现逻辑操作,init方法是一个用于初始化的通用函数(根据实际业务场景),最后用一个闭包(ProxySingletonCreateDiv)保证实例的唯一性

惰性单例

惰性单例指的是在需要的时候才创建对象实例,这种技术在实际开发中非常有用。以登录浮窗为例,实现方式有两种:

  1. 在页面加载完成后创建好浮窗,然后隐藏,点击登录按钮时显示
  2. 在页面加载完成后浮窗未创建,第一次点击登录按钮时创建浮窗

第二种方法的好处是,如果用户只是浏览网站,根本没打算登录,就可以少创建一个节点。

前面的单例模式是接近传统面向对象语言的实现,即单例对象从“类”中创建而来,这在面向对象的语言中是一种较好的实现方式,但JS本身并不是面向对象的语言,使用类的方式实现意义不大。下面结合JS的风格实现登录浮窗惰性单例

// 使用闭包,确保fn只会执行一次
var getSingle = function(fn) {
  var result;
  return function() {
    return result || (result = fn.apply(this, arguments));
  }
};

// 创建浮窗函数
var createSingleLoginLayer = getSingle(function() {
  var div = document.createElement('div');
  div.innerHTML = '我是登录浮窗';
  div.style.display = 'none';
  document.body.appendChild(div);
  return div;
});

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

当用户首次点击登录按钮,createSingleLoginLayer函数会创建一个浮窗并显示,而后再点击时getSingle函数会判断是否已经创建过,确保只创建一次。这是一种通用的实现方式,比如在使用JSONP跨域时,会创建一个script标签,然后动态改变他的src值,只需要getSingle中的参数即可

var createSingleScript = getSingle(function() {
  var script = document.createElement('script');
  document.body.appendChild(script);
  return script;
});

document.getElementById('getUserInfo').onclick = function() {
  var sc = createSingleScript();
  sc.src = 'https://test.com/api?callback=userinfo';
};
posted @ 2021-10-07 15:03  wmui  阅读(35)  评论(0编辑  收藏  举报