平時咱們在寫代碼時會偶爾用到策略模式的思想,但咱們卻不自知。今天學習了策略模式,特記錄以下:html
策略模式的定義是:定義一系列的算法,把他們一個個封裝起來,而且使它們能夠相互替換。算法
策略模式的目的是:將算法的使用和實現分離開來。一個基於策略模式的程序至少由兩部分組成。第一部分是一組策略類,策略類封裝了具體的算法,並負責具體的計算過程。第二部分是環境類Context,Context接受客戶的請求,隨後把請求委託給某一個策略類,Context要維持對某個策略對象的引用。app
在開發項目時,確定離不開表單檢驗這一個環節。dom
在編寫一個註冊頁面時,在點擊註冊按鈕以前,須要作幾條校驗邏輯:post
1.用戶名不能爲空;學習
2.密碼長度不能少於6位;this
3.手機號碼必須符合格式。spa
如今開始用策略模式實現:prototype
第一步:把校驗邏輯封裝成策略對象插件
var strategies={ isNotEmtpy:function(value, errorMsg){ if(value==''){ return errorMsg; } }, minLenth: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類,Validator類這裏做爲Context,負責接收用戶的請求並委託給策略對象。
var Validator = function(){ this.cache = []; //保存校驗規則 } Validator.prototype.add=function(dom, rules){ var _this=this; for(var i=0,rule;rule = rules[i++];){ (function(rule){ var strategyAry = rule.strategy.split(':'); var errorMsg = rule.errorMsg; _this.cache.push(function(){ var strategyName = strategyAry.shift(); strategyAry.unshift(dom.value); strategyAry.push(errorMsg); return strategies[strategyName].apply(dom, strategyAry); }) })(rule); } } Validator.prototype.start=function(){ console.log(this.cache) for( var i=0, validatorFunc; validatorFunc = this.cache[i++]; ){ var msg = validatorFunc(); if(msg){ return msg; } } }
有了上面的策略對象和環境類,剩下的就是調用了。一下附上完整代碼。
<!DOCTYPE html> <html> <head> <title>dmeo</title> </head> <body> <form id="registerForm" method="post"> 請輸入用戶名:<input type="text" name="username" /> 請輸入密碼:<input type="text" name="userpwd" /> <button>提交</button> </form> <script> /***************** 策略部分 ******************/ var strategies={ isNotEmtpy:function(value, errorMsg){ if(value==''){ return errorMsg; } }, minLenth: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; } } } /***************** 環境Context部分 ******************/ var Validator = function(){ this.cache = []; //保存校驗規則 } Validator.prototype.add=function(dom, rules){ var _this=this; for(var i=0,rule;rule = rules[i++];){ (function(rule){ var strategyAry = rule.strategy.split(':'); var errorMsg = rule.errorMsg; _this.cache.push(function(){ var strategyName = strategyAry.shift(); strategyAry.unshift(dom.value); strategyAry.push(errorMsg); return strategies[strategyName].apply(dom, strategyAry); }) })(rule); } } Validator.prototype.start=function(){ console.log(this.cache) for( var i=0, validatorFunc; validatorFunc = this.cache[i++]; ){ var msg = validatorFunc(); if(msg){ return msg; } } } /***************** 調用部分 ******************/ var validatorFn = function(){ var validator = new Validator(); validator.add(registerForm.username, [{strategy:'isNotEmtpy',errorMsg:'用戶名不能爲空!'},{strategy:'minLenth:4',errorMsg:'用戶名長度不能少於4位!'}] ); validator.add(registerForm.userpwd, [{strategy:'minLenth:6',errorMsg:'密碼長度不能少於6位!'}]); var errorMsg = validator.start(); return errorMsg; } var registerForm = document.getElementById('registerForm'); registerForm.onsubmit = function(){ var errorMsg = validatorFn(); if(errorMsg){ alert(errorMsg); return false; } } </script> </body> </html>
還能夠作成一個適合項目的校驗插件,方便調用。
策略模式還能夠有其餘使用場景:能夠用來封裝一系列的"業務規則",單出現不少判斷條件語句時,就能夠思考一下是否能夠使用策略模式。
若有錯誤,請指正!