戰略形式的定義是:
定義一系列的算法,把它們一個個封裝起來,而且是它們能夠互相替代。
- 戰略形式能夠防止代碼中的多重推斷前提。
- 戰略形式很好的表現了開放-關閉準繩,將一個個算法(解決方案)封裝在一個個戰略類中。便於切換,明白,擴大。
- 戰略中的種種算法能夠反覆應用在體系的各個地方,防止複製粘貼。
- 戰略形式在順序中或多或少的增添了戰略類。但比堆砌在營業邏輯中要清楚清楚明了。
- 違背起碼學問準繩,必須要相識種種戰略類,才更好的在營業中運用。
此文僅紀錄本人瀏覽《JavaScript設想形式與開闢實踐》這個本時的覺得,謝謝作者曾探寫出這麼好的一本書。若有搪突,若有毛病,請聯絡本人處置懲罰。
簡樸的營業場景
盤算員工年終獎須要依據差別的員工績效盤算差別的獎金。比方,績效為S的人年終獎有4倍工資。績效A的人年終獎有3倍工資,績效B的人有2倍工資。
用代碼完成:
var calculateBonus = function(performanceLevel, salary) {
if (performanceLevel === 'S') {
return salary * 4
}
if (performanceLevel === 'A') {
return salary * 3
}
if (performanceLevel === 'B') {
return salary * 2
}
}
calculateBonus('S', 2000) // 8000
calculateBonus('A', 2000) // 6000
實在上面一段代碼已能敷衍現在的場景。然則,當獎金的評定須要增添一個績效C,或許轉變績效A的盤算體式格局。此時須要變動上面這個calculateBonus
要領的內部結構,云云下去,這個要領內部將變得蕪雜。
設想形式中很主要的一點就是將穩定和變分離出來。這裏變的是怎樣算。穩定的是依據一個績效取得一個效果。所以上述代碼重寫,把種種算法封裝在一個個戰略類中(傳統面向對象的模擬):
var performanceS = function() {}
performanceS.prototype.calc = function(salary) {
return salary * 4
}
var performanceA = function() {}
performanceA.prototype.calc = function(salary) {
return salary * 3
}
var performanceB = function() {}
performanceB.prototype.calc = function(salary) {
return salary * 2
}
//獎金類Bonus
var Bonus = function() {
this.salary = null //原始工資
this.strategy = null // 績效品級對應的戰略對象
}
Bonus.prototype.setSalary = function(salary) {
this.salary = salary //設置工資
}
Bonus.prototype.setStrategy = function(strategy) {
this.strategy = strategy //設置員工績效對應的戰略對象
}
Bonus.prototype.getBonus = function() { //獵取獎金數額
return this.strategy.calc(this.salary) //把盤算獎金的操縱託付個對應的戰略對象
}
var bonus = new Bonus()
bonus.setSalary(10000)
bonus.setStrategy(new performanceA())
console.log(bonus.getBonus()) // 30000
JavaScript版本的戰略形式
在JavaScript中能夠將一個個戰略類寫成函數,然後封裝在對象中:
// 盤算獎金的例子
var strategies = {
S: function(salary) {
return salary * 4
},
A: function(salary) {
return salary * 3
},
B: function(salary) {
return salary * 2
}
}
var calculateBonus = function(level, salary) {
return strategies[level](salary)
}
console.log(calculateBonus('S', 10000)) // 40000
console.log(calculateBonus('S', 20000)) // 80000
更廣義的“算法”
戰略形式指的是一系列的算法(戰略),而且把它們封裝起來。盤算獎金的列子中就封裝了一些算法。實在世紀營業中也能夠應用戰略形式來封裝一些“營業劃定規矩”。
表單考證
在Web項目中每每有許多場景須要提交表單。前端在把數據提交到後端之前,須要舉行一波表單考證,來削減不必要的收集要求。在表單考證中每每會有多種校驗劃定規矩,頁面中能夠會有多個表單要舉行考證。此時能夠用戰略形式來完成一個表單考證:
<form action="" mothod="post" id="registerForm">
輸入用戶名: <input type="text" name="userName">
輸入暗碼: <input type="text" name="password">
輸入手機號碼:<input type="text" name="phoneNumber">
<button>提交</button>
</form>
<script>
var strategies = {
isNonEmpty: function(value, errorMsg){
if(value === ''){
return errorMsg
}
},
minLength: function(value, length, errorMsg){
if(value.length < length){
return errorMsg
}
},
isMobile: function(value, errorMsg){
if(!/(^1[3|5|8][0-9]{9}$)/.test(value)){
return errorMsg
}
}
}
// 定義Validator類
var Validator = function(){
this.cache = []
}
Validator.prototype.add = function(dom, rule, errorMsg){
var ary = rule.split(':')
this.cache.push(function(){
var strategy = ary.shift()
ary.unshift(dom.value)
ary.push(errorMsg)
return strategies[ strategy ].apply(dom, ary)
})
}
Validator.prototype.start = function(){
for (var i = 0,validatorFunc;validatorFunc = this.cache[i++];){
var msg = validatorFunc()
if(msg){
return msg
}
}
}
var validataFunc = function() {
var validator = new Validator()
// 增加校驗劃定規矩
validator.add(registerForm.userName,'isNonEmpty', '用戶名不能為空')
validator.add(registerForm.password,'minLength:6', '暗碼長度不能少於6位')
validator.add(registerForm.phoneNumber,'isMobile', '手機花樣不正確')
var errorMsg = validator.start()
return errorMsg
}
var registerForm = document.getElementById('registerForm')
registerForm.onsubmit = function(){
var errorMsg = validataFunc()
if (errorMsg) {
console.log(errorMsg)
return false
}
}
</script>
總結
- 在一樣平常開闢中一些東西函數能夠封裝在一起,構成本身的東西庫。削減不必要的代碼複製粘貼。
- 覺得敲代碼頭腦更主要啦,這裏戰略形式表現了開放-關閉準繩下降代碼的耦合度。這些理念都是我本身在敲代碼的路上要逐步進修和積聚的。
- 敲出來的代碼不能只要本身熟悉。要多注重細節,時候去想哪些代碼能夠再多完美。
- 固然不是一切的東西都要分來分去,一個簡樸的需求為了設想形式而去設想形式也是不可取的。
love & peace
參考
《JavaScript設想形式與開闢實踐》—— 曾探