今天我们来学习JavaScript常用的设计模式——单例模式

# 定义

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

也就是说它是唯一的,而且可以全局访问

单例与之对应的是多例,一般我们创建一个类,它可以进行实例化出很多对象,这就是多例,而单例模式只能实例化出一个对象。这个实例对象可以被缓存,可以被复用。

# 应用场景

当在开发中遇到了一些内容,感觉重复使用了很多次,如果可以将这个对象缓存下来,每次都是使用这个一个实例对象,而不是重新创建一个对象,这里就可以使用单例模式了。

比如在前端的页面开发中,我们的登录弹窗一般都是唯一的,不管点击多少次,登录弹窗都只会被创建一个。而且这个弹窗应该被缓存,这里可以提高页面的渲染效率,所以这个登录弹窗就可以用单例模式来创建。

# 使用前

我们要创建一个登录弹窗

// 业务逻辑:创建登录弹窗
function createLoginLayer(){
  // 创建一个登录弹窗盒子
  const div = document.createElement("div");
  div.innerHTML = "登录弹窗";
  // 将弹窗样式设置为不可见
  div.style.display = "none";
  // 将盒子添加到页面中
  document.body.appendChild(div);
  // 返回这个登录弹窗盒子
  return div;
};

然后给登录按钮绑定点击事件,点击上去之后,就创建一个弹窗,并将弹窗显示在页面中。

// 给登录按钮绑定单击事件
document.getElementById("loginBtn").onclick = () => {
  // 创建一个登录弹窗
  const loginLayer = createLoginLayer();
  // 将登录弹窗显示出来
  loginLayer.style.display = "block";
};

这样每次点击登录按钮,都会创建一个登录弹窗,会消耗很多的资源。我们的登录弹窗可以是唯一的,缓存下来的对象,我们考虑使用单例模式来重构我们的代码

# 使用后

使用 闭包 来实现单例模式

// 接受参数是一个函数
function getSingle(fn) {
  // 定义一个变量,用来标识当前是否已经创建过此对象
  let result = null;
  // 返回一个函数
  return function(...args) {
    // 形成闭包,将result缓存下来了
    if(result == null){
      // 如果result==null,将传入的函数fn执行结果赋值给result;在这里就是创建一个登录弹窗盒子
      result = fn.apply(this, args)
    }
    // 返回result这个对象
    return result
  };
};

这段代码保证了登录弹窗始终只有一个,也就是说后面每次创建登录弹窗都是直接使用第一次创建出来的弹窗,而不是再创建一个新的。

业务逻辑:创建登录弹窗

function createLoginLayer(){
  // 创建一个登录弹窗盒子
  const div = document.createElement("div");
  div.innerHTML = "登录弹窗";
  // 将弹窗样式设置为不可见
  div.style.display = "none";
  // 将盒子添加到页面中
  document.body.appendChild(div);
  // 返回这个登录弹窗盒子
  return div;
};

使用单例模式

// getSingle返回一个用来创建登录弹窗的函数
const createSingleLoginLayer = getSingle(createLoginLayer);

给登录按钮绑定点击事件

document.getElementById("loginBtn").onclick = () => {
  const loginLayer = createSingleLoginLayer();
  loginLayer.style.display = "block";
};
上次更新: 2022/4/18 18:10:13