单例模式(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