0
点赞
收藏
分享

微信扫一扫

【JS】168-JavaScript设计模式——策略模式

余寿 2022-10-13 阅读 116

【JS】168-JavaScript设计模式——策略模式_d3

五、策略模式(Strategy Pattern)

1.概念介绍

策略模式(Strategy Pattern):封装一系列算法,支持我们在运行时,使用相同接口,选择不同算法。它的目的是为了将算法的使用与算法的实现分离开来

策略模式通常会有两部分组成,一部分是策略类,它负责实现通用的算法,另一部分是环境类,它用户接收客户端请求并委托给策略类。

2.优缺点

2.1优点

  • 有效地避免多重条件选择语句;
  • 支持开闭原则,将算法独立封装,使得更加便于切换、理解和扩展;
  • 更加便于代码复用;

2.2缺点

  • 策略类会增多;
  • 所有策略类都需要对外暴露;

3.基本案例

我们可以很简单的将策略和算法直接做映射:

1. ​​let add = {​​
2. ​​ "add3" : (num) => num + 3,​​
3. ​​ "add5" : (num) => num + 5,​​
4. ​​ "add10": (num) => num + 10,​​
5. ​​}​​
6. ​​let demo = (type, num) => add[type](num);​​
7. ​​console.log(demo('add3', 10)); // 13​​
8. ​​console.log(demo('add10', 12)); // 22​​

然后我们再把每个策略的算法抽出来:

4.表单验证案例

1. let fun3  = (num) => num + 3;​​
2. ​​let fun5 = (num) => num + 5;​​
3. ​​let fun10 = (num) => num + 10;​​
4. ​​let add = {​​
5. ​​ "add3" : (num) => fun3(num),​​
6. ​​ "add5" : (num) => fun5(num),​​
7. ​​ "add10": (num) => fun10(num),​​
8. ​​}​​
9. ​​let demo = (type, num) => add[type](num);​​
10. ​​console.log(demo('add3', 10)); // 13​​
11. ​​console.log(demo('add10', 12)); // 22​​

我们需要使用策略模式,实现一个处理表单验证的方法,无论表单的具体类型是什么都会调用验证方法。我们需要让验证器能选择最佳的策略来处理任务,并将具体的验证数据委托给适当算法。

我们假设需要验证下面的表单数据的有效性:

1. ​​let data = {​​
2. ​​ name : 'pingan',​​
3. ​​ age : 'unknown',​​
4. ​​ nickname: 'leo',​​
5. ​​}​​

这里需要先配置验证器,对表单数据中不同的数据使用不同的算法:

1. ​​validator.config = {​​
2. ​​ name : 'isNonEmpty',​​
3. ​​ age : 'isNumber',​​
4. ​​ nickname: 'isAlphaNum',​​
5. ​​}​​

并且我们需要将验证的错误信息打印到控制台:

1. ​​validator.validate(data);​​
2. ​​if(validator.hasErrors()){​​
3. ​​ console.log(validator.msg.join('\n'));​​
4. ​​}​​

接下来我们才要实现 ​validator​​中具体的验证算法,他们都有一个相同接口 ​validator.types​​,提供 ​validate()​​方法和 ​instructions​帮助信息:

1. ​​// 非空值检查​​
2. ​​validator.types.isNonEmpty = {​​
3. ​​ validate: function(value){​​
4. ​​ return value !== '';​​
5. ​​ }​​
6. ​​ instructions: '该值不能为空'​​
7. ​​}​​

2. 
3. ​​// 数值类型检查​​
4. ​​validator.types.isNumber = {​​
5. ​​ validate: function(value){​​
6. ​​ return !isNaN(value);​​
7. ​​ }​​
8. ​​ instructions: '该值只能是数字'​​
9. ​​}​​
10.
11. ​​// 检查是否只包含数字和字母​​
12. ​​validator.types.isAlphaNum = {​​
13. ​​ validate: function(value){​​
14. ​​ return !/[^a-z0-9]/i.test(value);​​
15. ​​ }​​
16. ​​ instructions: '该值只能包含数字和字母,且不包含特殊字符'​​
17. ​​}​​

最后就是要实现最核心的 ​validator​对象:

总结这个案例,我们可以看出 ​validator​​对象是通用的,需要增强 ​validator​​对象的方法只需添加更多的类型检查,后续针对每个新的用例,只需配置验证器和运行 ​validator()​方法就可以。

1. let validator = {​​
2. ​​ types: {}, // 所有可用的检查​​
3. ​​ msg:[], // 当前验证的错误信息​​
4. ​​ config:{}, // 验证配置​​
5. ​​ validate: function(data){ // 接口方法​​
6. ​​ let type, checker, result;​​
7. ​​ this.msg = []; // 清空错误信息​​
8. ​​ for(let k in data){​​
9. ​​ if(data.hasOwnProperty(k)){​​
10. ​​ type = this.config[k];​​
11. ​​ checker = this.types[type];​​
12. ​​ if(!type) continue; // 不存在类型 则 不需要验证​​
13. ​​ if(!checker){​​
14. ​​ throw {​​
15. ​​ name: '验证失败',​​
16. ​​ msg: `不能验证类型:${type}`​​
17. ​​ }​​
18. ​​ }​​
19. ​​ result = checker.validate(data[k]);​​
20. ​​ if(!result){​​
21. ​​ this.msg.push(`无效的值:${k},${checker.instructions}`);​​
22. ​​ }​​
23. ​​ }​​
24. ​​ }​​
25. ​​ return this.hasErrors();​​
26. ​​ }​​
27. ​​ hasErrors: function(){​​
28. ​​ return this.msg.length != 0;​​
29. ​​ }​​
30. ​​}​​

5.小结

日常开发的时候,还是需要根据实际情况来选择设计模式,而不能为了设计模式而去设计模式。通过上面的学习,我们使用策略模式来避免多重条件判断,并且通过开闭原则来封装方法。我们应该多在开发中,逐渐积累自己的开发工具库,便于以后使用。

参考资料

  1. 《JavaScript Patterns》

【JS】168-JavaScript设计模式——策略模式_d3_02

举报

相关推荐

0 条评论