网站开发要花费多少钱,广告推广平台赚取佣金,网站的性能特点,高端品牌网站定制设计文章目录 1、使用策略模式计算奖金2、JavaScript 版本的策略模式3、应用#xff1a;表单验证3.1 用策略模式进行表单验证3.2 给某个文本输入框添加多种校验规则 4、策略模式的优缺点 策略模式的定义是#xff1a;定义一系列的算法#xff0c;把它们一个个封装起来#xff0… 文章目录 1、使用策略模式计算奖金2、JavaScript 版本的策略模式3、应用表单验证3.1 用策略模式进行表单验证3.2 给某个文本输入框添加多种校验规则 4、策略模式的优缺点 策略模式的定义是定义一系列的算法把它们一个个封装起来并且使它们可以相互替换
1、使用策略模式计算奖金
假如有个需求 绩效为 S 的人年终奖有 4 倍工资绩效为 A 的人年终奖有 3 倍工资而绩效为 B 的人年终奖是 2 倍工资
1.1 最初代码实现
var calculateBonus function (performanceLevel, salary) {if (performanceLevel S) {return salary * 4;}if (performanceLevel A) {return salary * 3;}if (performanceLevel B) {return salary * 2;}
}
console.log(calculateBonus(B, 3000));
console.log(calculateBonus(A, 5000));缺点
calculateBonus 函数包含了很多 if-else 语句这些语句需要覆盖所有的逻辑分支calculateBonus 函数缺乏弹性如果增加了一种新的绩效等级 C或者想把绩效 S 的奖金 系数改为 5那我们必须深入 calculateBonus 函数的内部实现这是违反开放封闭原则的算法的复用性差如果在程序的其他地方需要重用这些计算奖金的算法呢我们的选择 只有复制和粘贴
1.2 使用组合函数重构代码 使用组合函数来重构代码我们把各种算法封装到一个个的小函数里面
var performanceS function (salary) {return salary * 4;
}
var performanceA function (salary) {return salary * 3;
}
var performanceB function (salary) {return salary * 2;
}var calculateBonus function (performanceLevel, salary) {if (performanceLevel S) {return performanceS(salary);}if (performanceLevel A) {return performanceA(salary);}if (performanceLevel B) {return performanceB(salary);}
}console.log(calculateBonus(A, 2000));问题calculateBonus 函数有可能越来越庞大而且在系统变化的时候缺乏弹性
1.3 使用策略模式重构代码 一个基于策略模式的程序至少由两部分组成 第一个部分是一组策略类策略类封装了具体的算法并负责具体的计算过程。 第二个部分是环境类 ContextContext 接受客户的请求随后把请求委托给某一个策略类
// 定义绩效的计算规则
var performanceS function () { };
performanceS.prototype.calculate function (salary) {return salary * 4;
}
var performanceA function () { };
performanceA.prototype.calculate function (salary) {return salary * 3;
}
var performanceB function () { };
performanceB.prototype.calculate 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.calculate(this.salary);// 把计算奖金的操作委托给对应的策略对象
}var bonus new Bonus();
bonus.setSalary( 10000 );
bonus.setStrategy( new performanceS() ); // 设置策略对象
console.log( bonus.getBonus() ); // 输出40000
bonus.setStrategy( new performanceA() ); // 设置策略对象
console.log( bonus.getBonus() ); // 输出30000 2、JavaScript 版本的策略模式
上在 JavaScript 语言中函数也是对象所以更简单和直接的做法是把 strategy 直接定义为函数
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, 3000)); // 12000
console.log(calculateBonus(B, 1000)); // 20003、应用表单验证
做如下表单验证
用户名不能为空。密码长度不能少于 6 位。手机号码必须符合格式
3.1 用策略模式进行表单验证
把这些校验逻辑都封装成策略对象
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(:); // 把 strategy 和参数分开this.cache.push(function () {// 把校验的步骤用空函数包装起来并且放入 cachevar strategy ary.shift(); // 用户挑选的 strategyary.unshift(dom.value); // 把 input 的 value 添加进参数列表ary.push(errorMsg); // 把 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 validator new Validator();
validator.add({ value: }, isNonEmpty, 用户名不能为空);
validator.add({ value: 1234 }, minLength:6, 密码长度不能少于 6 位);
var errorMsg validator.start();
console.log(errorMsg)3.2 给某个文本输入框添加多种校验规则
/***********************策略对象**************************/
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, rules) {var self this;for (var i 0, rule; (rule rules[i]); ) {(function (rule) {var strategyAry rule.strategy.split(:);var errorMsg rule.errorMsg;self.cache.push(function () {var strategy strategyAry.shift();strategyAry.unshift(dom.value);strategyAry.push(errorMsg);return strategies[strategy].apply(dom, strategyAry);});})(rule);}
};
Validator.prototype.start function () {for (var i 0, validatorFunc; (validatorFunc this.cache[i]); ) {var errorMsg validatorFunc();if (errorMsg) {return errorMsg;}}
};/***********************客户调用代码**************************/
var validataFunc function () {var validator new Validator();validator.add({ value: }, [{strategy: isNonEmpty,errorMsg: 用户名不能为空,},{strategy: minLength:6,errorMsg: 用户名长度不能小于 10 位,},]);validator.add({ value: 123 }, [{strategy: minLength:6,errorMsg: 密码长度不能小于 6 位,},]);validator.add({ value: 1255555555 }, [{strategy: isMobile,errorMsg: 手机号码格式不正确,},]);var errorMsg validator.start();return errorMsg;
};var errorMsg validataFunc();
if (errorMsg) {console.warn(errorMsg);return false;
}4、策略模式的优缺点
优点
避免多重条件选择语句策略模式提供了对开放—封闭原则的完美支持将算法封装在独立的 strategy 中使得它们易于切换易于理解易于扩展策略模式中的算法也可以复用在系统的其他地方从而避免许多重复的复制粘贴工作
缺点
使用策略模式会在程序中增加许多策略类或者策略对象要使用策略模式必须了解所有的 strategy必须了解各个 strategy 之间的不同点这样才能选择一个合适的 strategy