定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。
目的:将算法的使用和算法的实现分离开来。
比如:
if(input == 'A'){ return 1; } if(input == 'B'){ return 2; } if(input == 'C'){ return 3; } //或者 switch(input){ case 'A': console.log(1); break; case 'B': console.log(2); break; case 'C': console.log(3); break; }
对于这种有多个if-else和switch语句的情况,可以使用策略模式来处理。
策略模式有两部分组成:
一、策略类:封装了具体的算法,并负责具体计算过程。
二、环境类:接受客户的请求,然后将请求委托给某个策略类
//策略类Strategy var strategies = { "A": function(num){ return 1 + num; }, "B": function(num){ return 2 + num; }, "C": function(num){ return 3 + num; } }; //环境类Context var calculate = function(level,num){ return strategies[level](num); }; //调用 result = calculate('A',10);
使用策略模式也可以用来封装一系列的业务规则,只要这些业务规则指向的目标一致,并且可以被替换使用,我们就可以用策略模式来封装它们。
表单校验:
一般写法:
function checkForm(){ if($("#name").val()==''){ alert('用户名不能为空!'); return false; } if($("#password").val().length<6){ alert('密码长度不能少于6位!'); return false; } if(!/(^1[3|5|8][0-9]{9}$)/.test($("#phone").val())){ alert('手机号格式不正确!'); return false; } }
使用“策略模式”:
/***********************策略对象Strategy***********************/ var strategise={ isEmpty: 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类Context***********************/ var Validator= function () { this.cache=[]; //保存校验规则 }; Validator.prototype.add = function(dom,rules){ var self = this; for(var i=0, rule; rule=rules.strategy.split(":")){ (function(rule){ var strateAry = rule.strategy.split(":"); var errorMsg = rule.errorMsg; self.cache.push(function(){ var strategy = strateAry.shift();//把数组的第一个元素从其中删除。 strateAry.unshift(dom.val()); //向数组的开头添加input元素的值。 strateAry.push(errorMsg); //在数组尾部添加error信息 return strategies[strategy].apply(dom,strateAry); }); })(rule) } }; Validator.prototype.start = function(){ for(var i=0, Func; Func=this.cache[i];i++){ var errorMsg = Func(); if(errorMsg){ return errorMsg; } } }; /***********************调用***********************/ var checkForm = function(){ var validator = new Validator(); validator.add($("#name"),[{ strategy: 'isEmpty', errorMsg: '用户名不能为空!' },{ strategy: 'minLength:6', errorMsg: '用户名长度不能小于6位' }]); validator.add($("#password"),[{ strategy: 'minLength:6', errorMsg: '密码长度不能小于6位' }]); validator.add($("#phone"),[{ strategy: 'isMobile', errorMsg: '手机号格式不正确!' }]); var errorMsg = validator.start(); return errorMsg; } $("form").submit(function(){ var errorMsg = checkForm(); if(errorMsg){ alert(errorMsg); return fasle; } });
优点:
1、采用组合、委托和多态等技术和思想,有效地避免多重条件选择语句。
2、对“开放封闭原则”完美支持,将算法独立封装在strategy,使得它们易于切换、理解和扩展。
3、策略模式中的算法也可以复用在系统的其他地方,从而避免重复的复制粘贴工作。
4、利用组合和委托让Context拥有执行算法的能力,这也是继承的一种轻便替代方案。