We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
俗话说,条条大路通罗马,完成一件事情,我们往往有很多选择,根据自身不同的条件我们可以有不同的选择方案。比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路。
这类选择过程也即是我们即将学习的策略模式。
策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
示例:编写一个计算奖金(bonus)的算法,薪资(salary) 为最小单元
可以看出,计算出员工奖金,我们需要知道员工的级别及薪资,我们可以编写一个方法,将级别和薪资当做参数传进去,这样我们就可以得到员工奖金。如下:
const calculateBonus = (performanceLevel, salary) => { if (performanceLevel === 'S') { return salary * 3 } if (performanceLevel === 'A') { return salary * 2 } if (performanceLevel === 'B') { return salary * 1 } } calculateBonus('S', 8000)
可以发现,这段代码十分简单,但是存在着显而易见的缺点。
在javascript中,声明一个对象的成本是很低的,我们根据策略模式的定义来改造下,上面计算函数我们完全可以简化成一个对象来进行维护,key是级别,value则是一个计算奖金的函数,代码如下:
const strategies = { 'S': salary => salary * 3, 'A': salary => salary * 2, 'B': salary => salary * 1 }; const calculateBonus = (level, salary) => strategies[ level ]( salary ) calculateBonus( 'S', 20000 )
这样一来,我们消除了大片的if-esle条件分支语句,使实现过程更加简洁,只需维护好strategies这个策略对象即可。
以上示例我们可以了解到策略模式的基本使用,那在我们实际开发过程,其实很多地方都可以用策略模式来进行改进,比如我们前端的一些校验,比较急躁的时候可能会出现上面庞大的if-else来进行各类验证条件的编写,那现在我们用策略模式来改进试试看,实现代码如下:
// 策略对象 const strategies = { isNonEmpty: (value, errorMsg) => { if (value === '') { return errorMsg } }, minLength: (value, length, errorMsg) => { if (value.length < length) { return errorMsg } }, isMobile: (value, errorMsg) => { if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) { return errorMsg } } } // 处理校验的校验类 class Validator { constructor() { this.cache = [] } add (ele, rules) { for (let i = 0, rule; (rule = rules[i++]);) { const strategyAry = rule.strategy.split(':') const errorMsg = rule.errorMsg this.cache.push(() => { const strategy = strategyAry.shift() strategyAry.unshift(ele.value) strategyAry.push(errorMsg) return strategies[strategy].apply(ele, strategyAry) }) } } start () { for (let i = 0, validatorFunc; (validatorFunc = this.cache[i++]);) { const errorMsg = validatorFunc() if (errorMsg) { return errorMsg } } } } // demo const registerForm = { userName: { value: 'lalalalala' }, password: { value: 'mimamima' }, phoneNumber: { value: 13123456789 } } const validataFunc = () => { const validator = new Validator() validator.add(registerForm.userName, [ { strategy: 'isNonEmpty', errorMsg: '用户名不能为空' }, { strategy: 'minLength:6', errorMsg: '用户名长度不能小于 6 位' } ]); validator.add(registerForm.password, [ { strategy: 'minLength:6', errorMsg: '密码长度不能小于 6 位' } ]); validator.add(registerForm.phoneNumber, [ { strategy: 'isMobile', errorMsg: '手机号码格式不正确' } ]) const errorMsg = validator.start() // 开始校验,并取得校验后的返回信息 return errorMsg } const errorMsg = validataFunc() if (errorMsg) { console.log(errorMsg) }
这样我们按照策略模式新增并维护一个策略类,然后按照规则添加各数据项的校验就好,保证了功能代码可读性及扩展性。
实际开发过程,当发现一个方法逐渐变得庞大,if-else写得让你难受的时候,试试策略模式改造能否解决痛点。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
俗话说,条条大路通罗马,完成一件事情,我们往往有很多选择,根据自身不同的条件我们可以有不同的选择方案。比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路。
这类选择过程也即是我们即将学习的策略模式。
策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
示例:编写一个计算奖金(bonus)的算法,薪资(salary) 为最小单元
可以看出,计算出员工奖金,我们需要知道员工的级别及薪资,我们可以编写一个方法,将级别和薪资当做参数传进去,这样我们就可以得到员工奖金。如下:
可以发现,这段代码十分简单,但是存在着显而易见的缺点。
分支。
系数改为 5,那我们必须深入 calculateBonus 函数的内部实现,这是违反开放-封闭原则的。
只有复制和粘贴。
在javascript中,声明一个对象的成本是很低的,我们根据策略模式的定义来改造下,上面计算函数我们完全可以简化成一个对象来进行维护,key是级别,value则是一个计算奖金的函数,代码如下:
这样一来,我们消除了大片的if-esle条件分支语句,使实现过程更加简洁,只需维护好strategies这个策略对象即可。
以上示例我们可以了解到策略模式的基本使用,那在我们实际开发过程,其实很多地方都可以用策略模式来进行改进,比如我们前端的一些校验,比较急躁的时候可能会出现上面庞大的if-else来进行各类验证条件的编写,那现在我们用策略模式来改进试试看,实现代码如下:
这样我们按照策略模式新增并维护一个策略类,然后按照规则添加各数据项的校验就好,保证了功能代码可读性及扩展性。
总结
实际开发过程,当发现一个方法逐渐变得庞大,if-else写得让你难受的时候,试试策略模式改造能否解决痛点。
The text was updated successfully, but these errors were encountered: