单例模式(Singleton)
 Jul 27, 2022 · 
  3 Min Read 
 单例模式的定义是:保证一个仅有一个实例,并提供一个访问它的全局访问点。
解析:即实现单例要满足两点。一、仅且有一个实例;二、有一个访问它的全局访问点。
使用场景:
- 线程池
- 全局缓存
- 登录框
- 事件只绑定一次 等等
一般我们想到的实现方法是:
const CreateDiv = (function () {  let instance;  const CreateDiv = function (html) {    if (instance) return instance; // 重点在于这步,判断是否有实例化一次    this.html = html;    this.init();    return instance = this;  }
  CreateDiv.prototype.init = function () {    const div = document.createElement('div');    div.innerText = this.html;    document.body.appendChild(div);  }
  return CreateDiv;})();
const a = new CreateDiv('kim1');const b = new CreateDiv('kim2');console.log(a === b) // true缺点:这个构造函数怪怪的。而且当我们需要实现一个 iframe 或者其他需求的时候,又要重新复制一次代码进行改写。
- 使用变量来判断
const createLoginLayer = (function () {  let div;  return function () {    if (!div) {      div = document.createElement('div');      div.innerHTML = '我是浮窗';      div.style.display = 'none';      document.body.appendChild(div);    }    return div;  }})();
const popup = createLoginLayer();缺点:违反了单一职责原则,创建对象和管理单例的逻辑都放在一个函数里,如果下一次业务不同,则又需要照抄一遍。
最终方案:将管理单例和创建对象分开开了,以后则需要传入不同的创建对象函数则可以实现单例模式。
function f(fn) {  let instance;  return function () {    return instance || (instance = fn.apply(this, arguments))  }}
function a() {  const temp = new Object();  return temp;}
const create = f(a)console.log(create() === create())  // true例如:实现一个登陆弹窗,当第一次点击登陆时,创建弹窗的对象,第二次则继续沿用之前创建好的对象。 PS:这里省略样式和弹窗的文本,只是简单的添加一个元素到 body 节点上。
<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Title</title></head><body><button id="login">登陆</button>
<script>  document.getElementById('login').addEventListener('click', function () {    const loginDiv = login()    console.log(loginDiv)  })
  function getSingle(fn) {    let instance;    return function () {      return instance || (instance = fn.apply(this, arguments))    }  }
  function createDiv() {    const div = document.createElement('div');    div.innerHTML = '我是浮窗';    // TODO add style or edit HTML    document.body.appendChild(div);    return div  }
  const login = getSingle(createDiv);</script></body></html> Last edited Feb 15