策略模式(Strategy) 定義:將定義的一組演算法封裝起來,使其相互之間可以替換。封裝的演算法具有一定的獨立性,不會隨客戶端的變化而變化 廢話不多說,先來個例子 上面的例子,一定會有人這麼寫的,你要說沒有我也沒辦法(~ ̄▽ ̄)~,這樣寫首先不利於維護,其實也不好方便擴展 改進一下: 上面的例子就可以 ...
策略模式(Strategy)
定義:將定義的一組演算法封裝起來,使其相互之間可以替換。封裝的演算法具有一定的獨立性,不會隨客戶端的變化而變化
廢話不多說,先來個例子
// 例如要寫一個計算兩個數加減乘除的方法,會有人這麼寫
countNum(type, num1, num2) {
if(type === 'add'){
return num1 + num2
} else if(type === 'subtract'){
return num1 - num2
} else if(type === 'multiply'){
return num1 * num2
} else {
return num1 / num2
}
}
countNum('add', 9, 3) // 12
countNum('subtract', 9, 3) // 6
countNum('multiply', 9, 3) // 27
countNum('', 9, 3) // 3
上面的例子,一定會有人這麼寫的,你要說沒有我也沒辦法(~ ̄▽ ̄)~,這樣寫首先不利於維護,其實也不好方便擴展
改進一下:
let countNum = {
add(num1, num2) {
return num1 + num2
},
subtract(num1, num2) {
return num1 - num2
},
multiply(num1, num2) {
return num1 * num2
},
divide(num1, num2) {
return num1 / num2
},
}
countNum.add(9, 3) // 12
countNum.subtract(9, 3) // 6
countNum.multiply(9, 3) // 27
countNum.divide(9, 3) // 3
上面的例子就可以看成是一個策略模式
now,現在有個需求,快要聖誕節,所以咧,超市中一部分商品8折出售,一部分9折出售,等到元旦還要搞大事,普通用戶滿100返30,VIP用戶滿100返50,用策略模式來實現
// 定義一個策略對象
let priceceStrategy = function(){
// 內部演算法對象
let strategy = {
return30(price){
return price + parseInt(price / 100) * 30
},
return50(price){
return price + parseInt(price / 100) * 50
},
price80(price){
return price * 80 / 100
},
price90(price){
return price * 90 / 100
}
}
// 策略方法調用介面
return {
strategyFunction(type, price) {
return strategy[type] && strategy[type](price)
},
// 添加演算法
addStrategy(type, fn){
strategy[type] = fn
}
}
}()
priceceStrategy.strategyFunction('return30', 100) // 130
priceceStrategy.strategyFunction('return50', 100) // 150
priceceStrategy.strategyFunction('price80', 100) // 80
priceceStrategy.strategyFunction('price90', 100) // 90
// 添加一個演算法
priceceStrategy.addStrategy('return70', (price) => {
return price + parseInt(price / 100) * 70
})
console.log(priceceStrategy.strategyFunction('return70', 100)) // 170
還有我們的表單驗證也可以使用策略模式
// 定義一個策略對象
let inputStrategy = function(){
// 內部演算法對象
let strategy = {
notNull(value){
return /\s+/.test(value) ? '請輸入內容' : ''
},
number(value){
return /^[0-9]+(\.[0-9]+)?$/.test(value) ? '' : '請輸入數字'
}
}
// 策略方法調用介面
return {
check(type, value) {
// 去除空白符
value = value.replace(/^\s+|\s+$/g, '')
return strategy[type] && strategy[type](value)
},
// 添加策略
addStrategy(type, fn){
strategy[type] = fn
}
}
}()
// 添加演算法
inputStrategy.addStrategy('nickName', (value) => {
return /^[a-zA-Z]\w{3,7}$/.test(value) ? '' : '請輸入4-8為昵稱'
})
總結
策略模式屬於對象行為型模式,主要針對一組演算法,將每一個演算法封裝到具有共同介面的獨立的類中,從而使得它們可以相互替換。策略模式使得演算法可以在不影響 到客戶端的情況下發生變化。通常,策略模式適用於當一個應用程式需要實現一種特定的服務或者功能,而且該程式有多種實現方式時使用。
策略模式中的三個對象:
- 環境對象:該類中實現了對抽象策略中定義的介面或者抽象類的引用。
- 抽象策略對象:它可由介面或抽象類來實現。
- 具體策略對象:它封裝了實現同不功能的不同演算法。
利用策略模式構建應用程式,可以根據用戶配置等內容,選擇不同有演算法來實現應用程式的功能。具體的選擇有環境對象來完成。採用這種方式可以避免由於使用條件語句而帶來的代碼混亂,提高應用程式的靈活性與條理性。
優點:
- 優化多重條件判斷,採用策略模式是的演算法更利於維護
- 可擴展性,策略模式提供了對“開閉原則”的完美支持,用戶可以在不修改原有系統的基礎上選擇演算法或行為,也可以靈活地增加新的演算法或行為。
- 策略類之間可以自由切換,由於策略類都實現同一個介面,所以使它們之間可以自由切換。
缺點:
- 由於選擇哪種演算法的決定權在用戶,所以對用戶來說就必須瞭解每種演算法的實現。
- 由於每種演算法間相互獨立,這樣對於一些複雜的演算法處理相同邏輯的部分無法實現共用,這就會造成一些資源的浪費。