Javascript设计模式与开发实践详解(二:策略模式)
来源:互联网 发布:北京供销大数据集团 编辑:程序博客网 时间:2024/06/05 15:34
上一章我们介绍了单例模式及JavaScript惰性单例模式应用
这一次我主要介绍策略模式
策略模式是定义一系列的算法,把它们一个个封装起来,并且让他们可以互相替换。
比方说在现实中很多时候也有很多途径到达同一个目的地,比如我们去某个地方旅游,可以选择坐飞机,乘火车,骑自行车等方式。
使用策略模式计算奖金
很多公司的年终奖是根据员工的工资基数和年底绩效来发放的。例如,绩效为 S 的人年终奖有4倍工资,绩效为 A 的人年终奖有3倍工资,绩效为 B 的人年终奖有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)}calculateBonus('A',10000); // 30000
值得一提的是以上代码并不符合策略模式定义
策略模式是定义一系列的算法,把它们一个个封装起来,并且让他们可以互相替换。
这句话理解起来就是定义一系列的算法,把它们各自封装成策略类,算法被封装在策略类内部的方法里。
因此我们必须做点改变在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',20000) ); // 80000
以上基本符合了策略模式的定义及写法。
更广义的算法
用策略模式仅仅来封装算法未免大材小用,在实际开发中,也可以用策略模式来封装一些业务规则。
接下来我们用策略模式来完成表单验证的例子。
表单验证
校验表单信息想必都是稀松平常的事情,假设我们正在编写一个注册的页面,在点击注册按钮之前,有如下几条校验逻辑。
1.用户名不能为空
2.密码长度不少于6位
3.手机号码必须符合格式
假设我们现在没有引入策略模式,那么普通的写法是这样的:
<body> <form action='xxx' id='registerForm' method='post'> please entry username : <input type='text' name='username' /> please entry password : <input type='text' name='password' /> please entry phoneNumber : <input type='text' name='phoneNumber' /> <button>submit</button> </form> <script> var registerForm = document.getElementById('registerForm') registerForm.onsubmit = function () { if(registerForm.username.value == ''){ alert('username cannot be none') return false; } if(registerForm.password.value.length < 6 ){ alert('password length cannot less than 6') return false; } if(!/(^1[3][5][8][0-9]{9}$)/.test(registerForm.phoneNumber.value)){ alert('phoneNumber format error') return false; } } </script></body>
可想而知这种面向过程的方法繁琐且不复用缺乏弹性,总而言之,我们必须用策略模式重构之。
注意我们的核心思想就是要写两个类: 一个策略类 一个内容类
用策略模式重构表单校验
第一步我们要把这些校验逻辑封装成策略对象,也就是策略类:
var strategies = { isNonEmpty: function (value ,errorMsg) { if(value == '') return errorMsg }, minLength: function (value,length,errorMsg) { if(value.length < length) return errorMsg },inMobile: function (value,errorMsg) { if(!/(^1[3][5][8][0-9]{9}$)/.test(value)) return errorMsg }};
ok ,现在我们开始写内容类。Validator 类在这里作为context ,负责接收用户的请求,并委托给strategy对象。
var Validator = function () {this.cache = []; // save the check format} Validator.prototype.add = function (dom,rule,errorMsg) {var ary = rule.split(':') // forExample : 'minLength:10' this.cache.push(function () { var strategy = ary.shift() // minLength ary.unshift(dom.value) // forExample : registerForm.username ary.push(errorMsg); // ary= [registerForm.username,10] return strategies[strategy].apply(dom,ary) //bring the dom & ary into strategies props.});};Validator.prototype.start = function () {for (var i = 0; ValidatorFunc; ValidatorFunc = this.cache[i++]) { var msg = ValidatorFunc(); if(msg) return msg; // if have return value then the check is failed.};}
如果我们没有写如何用户如何向Validator类发送请求,上面理解起来可能比较复杂。现在我们具体到表单看看。
var ValidatorFunc = function () {var validator = new Validator()/***************add some format by the prototype fun.*************************/ validator.add(registerForm.username,'isNonEmpty','username cannot be none'); validator.add(registerForm.password,'minLength:6','password cannot be none'); validator.add(registerForm.phoneNumber,'isMoblie','phoneNumber cannot be none'); var errorMsg = Validator.start() // get the check result return errorMsg // return the result. if exsit ...} var registerForm = document.getElementById('registerForm') registerForm.onsubmit = function () { var errorMsg = validatorFunc() // this is a instance!!! if(errorMsg) alert(errorMsg) return false}
这样我们大致完成了一个表单的策略模式重构(如果你能马上立刻看懂的话...)
值得一提的是我们现在可以非常轻松简单的修改校验规则,例如
validator.add(registerForm.username,'minLength:10','username cannot less than 10')
小结
策略模式是一种常用且有效的设计模式,我们可以总结出策略模式的一些优点。
- 有效避免多重条件选择语句
- 完美支持了开发--封闭原则
- 易于复用
作者:颜卿今天Coding了吗
链接:http://www.jianshu.com/p/ef53781f6ef2
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- Javascript设计模式与开发实践详解(二:策略模式)
- javaScript设计模式与开发实践-策略模式
- 《javascript设计模式与开发实践》阅读笔记(二)
- 【学习笔记javascript设计模式与开发实践(策略模式)----5】
- 【学习笔记javascript设计模式与开发实践(策略模式)----5】
- 策略模式--js设计模式与开发实践-7
- JavaScript设计模式与开发实践
- 《JavaScript设计模式与开发实践》
- JavaScript设计模式与开发实践笔记
- JavaScript设计模式与开发实践
- 策略模式与开发实践
- 《javascript设计模式与开发实践》阅读笔记(一)
- 《javascript设计模式与开发实践》阅读笔记(三)
- 《javascript设计模式与开发实践》阅读笔记(四)
- JavaScript设计模式与开发实践 – 观察者模式
- JavaScript设计模式与开发实践 – 观察者模式
- javaScript设计模式与开发实践-单例模式
- Java设计模式(二)策略模式详解
- android studio 无法调试安装到小米手机解决方法
- 项目中加载properties文件
- 位运算操作详解
- java反编译工具Luyten
- 图像/视频背景建模
- Javascript设计模式与开发实践详解(二:策略模式)
- Caused by: java.lang.ClassNotFoundException: Didn't find class ""on path: DexPathList[[zip file "/da
- MySQL 日期与时间戳的转换
- android shape的使用
- Python-27 类和对象:面向对象编程
- Windows连上Hadoop集群做分词练习
- Spring(八)SSH集成
- [五]Spring Boot 整合Mybatis 日志打印
- 解决Git push时error: failed to push some refs to...