★策略模式★
策略模式
我们在编程的时候,经常会遇到一套算法,具体使用哪个算法需要看情况。但是即使不用这一套算法,也要预先定义。此时为了是这一套算法易于维护,可以使用策略模式
比如说用户输入购买的汽油编号和加油升数,用来显示实时价格
- 89号汽油 5.35元/升
- 92号汽油 5.55元/升
- 95号汽油 5.75元/升
- 0号柴油 5.2元/升
先看非设计模式的算法
1 <script> 2 function calc(type, amount) { 3 if (type == 89) { 4 return amount * 5.3-+5; 5 } else if (type == 92) { 6 return amount * 5.55; 7 } else if (type == 95) { 8 return amount * 5.75; 9 } else if (type == 0) { 10 return amount * 5.2 11 } 12 } 13 var jiage = calc(0, 100) 14 console.log(jiage) 15 </script>
此时我们想一下,这就是所谓的一套算法,算的是什么,算的是价格。根据型优品型号号来算钱。所以我们可以以这个为出发点来设计策略模式
1 <script> 2 // 策略清单 3 var stra = { 4 "89": function(amount) { 5 return amount * 5.35; 6 }, 7 "92": function(amount) { 8 return amount * 5.55; 9 }, 10 "95": function(amount) { 11 return amount * 5.75; 12 }, 13 "0": function(amount) { 14 return amount * 5.2; 15 }, 16 }; 17 // 选择一种策略 18 var jiage = stra['92'](100) 19 console.log(jiage) 20 </script>
策略模式可以用于组合一系列算法,也可以组合一系列业务
比如我们需要通过成绩等级来计算学生的最终得分:
1 <script> 2 // 映射关系 3 var levelMap = { 4 S: 10, 5 A: 8, 6 B: 6, 7 C: 4 8 }; 9 // 组策略 10 var scoreLevel = { 11 // 基础分数值 12 baseScore: 80, 13 S: function() { 14 return this.baseScore + levelMap['S'] 15 }, 16 A: function() { 17 return this.baseScore + levelMap['A'] 18 }, 19 B: function() { 20 return this.baseScore + levelMap['B'] 21 }, 22 C: function() { 23 return this.baseScore + levelMap['C'] 24 } 25 }; 26 //获取策略 27 function getScore(level) { 28 // 返回的成绩 29 return scoreLevel[level] ? scoreLevel[level]() : 0; 30 } 31 console.log(getScore("S")) //90 32 console.log(getScore("A")) //88 33 console.log(getScore("B")) //86 34 console.log(getScore("C")) //84 35 console.log(getScore("D")) //0 36 </script>
比较经典的策略者模式就是关于表单校验的逻辑
1 <script> 2 // 错误信息 3 var errorMessage = { 4 default: "当前的输入格式不正确", 5 minLength: "输入的数据长度不够", 6 isNumber: "输入数据类型不是数字", 7 required: "内容不能为空" 8 } 9 // 规则集合 10 var rules = { 11 // 最大长度 12 minLength: function(value, length, errorMsg) { 13 if (value.length < length) { 14 return errorMsg || errorMessage['minLength']; 15 } 16 }, 17 // 数字类型的校验 18 isNumber: function(value, errorMsg) { 19 if (!/\d+/.test(value)) { 20 return errorMsg || errorMessage("isNumber") 21 } 22 }, 23 // 内容不能为空 24 required: function(value, errorMsg) { 25 if (value == '') { 26 return errorMsg || errorMessage("required") 27 } 28 } 29 }; 30 // 校验构造函数 31 function Validator() { 32 this.items = [] 33 }; 34 Validator.prototype.add = function(value, rule, errorMsg) { 35 // 接受参数 36 var arg = [value]; 37 // 超出length的提示语信息内容 38 if (rule.indexOf('minLength') !== -1) { 39 var temp = rule.split(":"); 40 arg.push(temp[1]); 41 // 强行给rule赋值为temp第0项的逻辑 42 rule = temp[0] 43 }; 44 arg.push(errorMsg); 45 // 存储校验参数 46 this.items.push(function() { 47 // rules是外面的规则集合,rule是函数的形参 48 return rules[rule].apply(null, arg) 49 }) 50 51 } 52 // 执行校验 53 Validator.prototype.start = function() { 54 for (var i = 0; i < this.items.length; i++) { 55 // 执行校验逻辑 56 var ret = this.items[i]() 57 if (ret) { 58 console.log(ret) 59 } 60 } 61 } 62 var validate = new Validator(); 63 validate.add("ccc", "isNumber", "数据类型为数字") 64 validate.add("123", "minLength:5", '最少输入5位') 65 var ret = validate.start() 66 </script>