模式是什麼
設計模式是:在軟體設計過程中針對「特定」問題的「簡潔而優雅」的解決方案。
在軟體開發的歷史中,沉澱了一些好的軟體設計,而設計模式便是給這些好設計取了個名字。「好的設計」並不是某人發明的。一個稍有經驗的程式設計師也許在不知不覺中數次使用過這些設計模式。
模式的意義
設計模式的意義是讓人們寫出可複用和可維護性高的程式。
舉個例子,假設有一個空房間,我們要日復一日地往裡面放一些東西。最簡單的辦法當然是把這些東西直接扔進去,但是時間久了,就會發現很難從這個房子裡找到自己想要的東西,要調整某幾樣東西的位置也不容易。
所以在房間裡做一些櫃子也許是個更好的選擇,雖然櫃子會增加我們的成本,但它可以在維護階段為我們帶來好處。使用這些櫃子存放東西的規則,或許就是一種模式。
所有設計模式的實現都遵循一條原則,即「找出程式中變化的地方,並將變化封裝起來」。
一個程式的設計總是可以分為可變的部分和不變的部分。當我們找出可變的部分,並且把這些部分封裝起來,那麼剩下的就是不變和穩定的部分。這些不變和穩定的部分是非常容易複用的。
熟悉這些模式的程式設計師,對某些模式的理解也形成了條件反射,當合適的場景出現時,他們可以很快地找到某種模式作為解決方案。
我們主要學習以下模式:
- 單例模式
- 策略模式
- 代理模式
- 釋出訂閱模式
- 命令模式
- 狀態模式
單例模式
單例模式的定義是:「保證僅有一個例項,並提供一個訪問它的全域性訪問點」。
單列模式場景
單例模式是一種常用的模式,有一些物件我們往往只需要一個,比如全域性快取、瀏覽器中的 window 物件等。
舉個前端的例子,網頁loading圖(菊花圖)。頁面整個生命週期,我們只需要生成一個loading就好了。既簡化了邏輯(不必去考慮多個請求開啟了多個loading)又減少了dom的建立。
實現單例
在javascript
中,函式是一等公民,所以例子我都優先使用函式來實現(原書是以物件導向的形式展現)
function generateInstance() {
return {
say() {
console.log(`hello`)
}
}
}
let single = (function() {
let instance // 哨兵變數
return function getSingle() {
if (!instance) {
// 如果還沒有生成例項,那麼生成一個。
instance = generateInstance()
}
return instance
}
})()
let a = single()
let b = single()
console.log(a === b) // true
以上就是一個單例的例子了。
我們利用閉包儲存了一個哨兵變數,用來判斷單例是否生成。
單例模式的優缺點
優點:
- 應用週期,只需例項化一次,對於生成例項開銷大的情況,可以提高效能。
- 方便管理,確保的所有的引用都是同一個例項。
缺點:
- 例項儲存在閉包,是無法銷燬的。
正規化
下面是一個生成單例的高階函式。
var getSingle = function(fn) {
var result
return function() {
return result || (result = fn.apply(this, arguments))
}
}
// 用法
let singeName = getSingle(() => `hello ${Math.random()}`)
let a = singeName()
let b = singeName()
console.log(a === b) // true