單例模式的定義是,保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。javascript
有一些對象,好比線程池/全局緩存/瀏覽器中的 window
對象等等,咱們只須要一個實例。下面將根據實際場景進行介紹。html
當咱們單擊登陸按鈕時,頁面中會出現一個登陸的浮窗,而這個登陸浮窗是惟一的,不管單擊多少次登陸按鈕,這個浮窗都只會被建立一次,那麼這個登陸浮窗就適合用單例模式來建立。java
傳統作法在頁面加載完成時,就建立好登陸浮窗,當用戶點擊登陸按鈕時,顯示登陸浮窗,實現代碼以下:git
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<button id="loginBtn">登陸</button>
<script type="text/javascript" src="index.js">
</script>
</body>
</html>
複製代碼
var loginLayer = (() => {
let div = document.createElement('div')
div.innerHTML = '我是登陸彈窗'
div.style.display = 'none'
document.body.appendChild(div)
return div
})()
document.getElementById('loginBtn').onclick = () => {
loginLayer.style.display = 'block'
}
複製代碼
源碼地址github
上述代碼有如下缺點:web
DOM
節點,浪費性能。如今優化一下,將代碼改成,在用戶點擊登陸按鈕後,才新增登陸浮窗的 DOM
節點。設計模式
代碼以下:瀏覽器
var createLoginLayer = () => {
let 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'
}
複製代碼
源碼地址緩存
上述代碼也存在缺陷,具體以下:markdown
DOM
節點更加浪費性能。實際上,咱們只須要建立一次登陸浮窗。
經過單例模式,重構上述代碼。
const createLoginLayer = () => {
const div = document.createElement('div')
div.innerHTML = '我是登陸彈窗'
div.style.display = 'none'
console.log(123)
document.body.appendChild(div)
return div
}
const createSingle = (function () {
var instance = {}
return function (fn) {
if (!instance[fn.name]) {
instance[fn.name] = fn.apply(this, arguments)
}
return instance[fn.name]
}
})()
const createIframe = function () {
const iframe = document.createElement('iframe')
document.body.appendChild(iframe)
iframe.style.display = 'none'
return iframe
}
const createSingleLoginLayer = createSingle(createLoginLayer)
const createSingleIframe = createSingle(createIframe)
document.getElementById('loginBtn').onclick = () => {
const loginLayer = createSingleLoginLayer
const iframe = createSingleIframe
loginLayer.style.display = 'block'
iframe.style.display = 'block'
}
複製代碼
通過重構,代碼作了如下優化:
createLoginLayer
/ createIframe
的職責和管理單例對象 createSingle
的職責分離,符合單一職責原則;iframe
/ script
等其餘標籤時,能夠直接複用該邏輯。單例模式是一種簡單但很是實用的模式,特別是惰性單例技術,在合適的時候才建立對象,而且只建立惟一的一個。更奇妙的是,建立對象和管理單例的職責被分佈在兩個不一樣的方法中,這兩個方法組合起來才具備單例模式的威力。
· 往期精彩 ·