0 設計模式分類
- 創建型:幫助創建對象(工廠模式、單例模式、建造者模式、原型模式)
- 結構型:幫助設計代碼結構(適配器模式、裝飾者模式、享元模式)
- 行為型:幫助組織模塊行為(策略模式、職責鏈模式、命令模式)
- 技巧型:優化代碼的技巧
1 策略模式
需求:用戶管理和組織管理中存在相同的處理操作:創建、編輯、詳情,針對編輯和詳情,對于不同字段又有不同的處理方式,導致最后寫了很多if else,那為什么不能復用,寫一段可維護的代碼?
export const processDefaultValueFn = {create: () => {},update: () => {},detail: () => {}
}export updateCaseFn = {string: () => {},boolean: () => {}
}
2 適配器模式
需求:組件數據來源由原來的單一來源改為多個接口來源,但原有接口無法改變,因此需要適配,在項目中,我們大多都是單一數據源
3 單例模式
定義:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點
例子:采用單例模式創建dom元素
//單一職責原則,該函數只用于創建DOM元素,不關注創建的DOM元素是什么,將創建DOM元素的內容代理至外部函數中
const createDOM = function(fn) {var resultreturn function() {return result || (fn.apply(this, arguments)) }
}const createDiv = function (){return div
}const createSpan = function(){return span
}createDOM(createDiv)
createDOM(createSpan)
4 代理模式
用法:當不方便訪問一個對象時,提供一個代理對象來控制對這個對象的訪問
緩存代理:例如useMemo
5 發布-訂閱模式
例如:登陸后需要進行一系列設置,導致后續有業務需要添加在登錄成功后的函數中,需要加代碼
通常寫法:
login.success(()=>{header.setAvatar(data)nav.setAvatar()
})
改進寫法:
$.ajax('',()=>{login.trigger(data)
})//各模塊監聽登錄成功的消息
const header = (()=>{login.listen('success',(data) => {header.setAvatar(data)})
})()
6 命令模式
應用場景:有些時候需要向某個對象發送請求,但是不知道請求的接收者是誰,請求的操作是什么。通過命令模式解耦請求發送者和請求接收者之間的聯系
優點:
- 發布者和接收者之間解耦
- 可以使用棧來維護一個請求隊列,從而實現撤銷、連續點擊等功能
缺點:
- 額外增加一個命令對象,使得代碼變得復雜
7 組合模式
分析:創建一顆命令樹,每個樹的葉子節點包含一個execute方法,js中實現組合模式的難點在于必須保證組合對象和葉對象擁有相同的方法
缺點:樹的結果如果比較復雜,性能會受到影響,可以采用職責鏈模式避免遍歷整棵樹
應用場景:表示對象的部分-整體結構,統一對待樹中的所有對象
8 享元模式(用于性能優化,時間換空間)
該模式要求將對象的屬性劃分為內部屬性和外部屬性
- 內部屬性:存儲于對象內部,可以被一些對象共享,獨立于具體場景,不會改變
- 外部屬性:取決于具體場景,并根據場景變化,不能共享
應用場景:多文件上傳優化
適用場景:
- 使用大量對象造成很大的內存開銷
- 對象的大多數狀態可以轉換成外部狀態
使用閉包來私有化對象
const uploadFactory = function() {const obj = {}return {create: function(type) {if (obj[type]) {return obj[type]}return obj[type] = new Upload(type)} }
}
9 中介者模式
其實就是發布-訂閱模式
應用場景:對象之間的耦合性太高,更改一個對象后還需更改另一個對象,中介者模式使對象之間的關系解耦
缺點:中介者對象可能會非常復雜
10 裝飾器模式
給某個對象動態添加某個功能,并且不影響使用這個對象的其他對象