策略模式学习笔记
平时我们在写代码时会偶尔用到策略模式的思想,但我们却不自知。今天学习了策略模式,特记录如下:
策略模式的定义是:定义一系列的算法,把他们一个个封装起来,并且使它们可以相互替换。
策略模式的目的是:将算法的使用和实现分离开来。一个基于策略模式的程序至少由两部分组成。第一部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。第二部分是环境类Context,Context接受客户的请求,随后把请求委托给某一个策略类,Context要维持对某个策略对象的引用。
在开发项目时,肯定离不开表单检验这一个环节。
在编写一个注册页面时,在点击注册按钮之前,需要做几条校验逻辑:
1.用户名不能为空;
2.密码长度不能少于6位;
3.手机号码必须符合格式。
现在开始用策略模式实现:
第一步:把校验逻辑封装成策略对象
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>
还可以做成一个适合项目的校验插件,方便调用。
策略模式还可以有其他使用场景:可以用来封装一系列的"业务规则",单出现很多判断条件语句时,就可以思考一下是否可以使用策略模式。
如有错误,请指正!