介绍

策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。将不变的部分和变化的部分隔开是每个设计模式的主题,策略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来

一个基于策略模式的程序至少由两部分构成,第一个部分是一组策略类,包含了具体的算法实现;第二个部分是环境类,它可以接收客户的请求,随后把请求委托给指定的策略类,所以,环境类中一定要维持对策略类的引用。

JavaScript策略模式实现

JavaScript 中策略类可以用一个包裹各种算法实现的对象来实现,环境类则用函数来实现,代码如下:

  1. // 策略对象(类)
  2. var strategies = {
  3. 'S': function(salary) {
  4. return salary * 4;
  5. },
  6. 'A': function(salary) {
  7. return salary * 3;
  8. },
  9. 'B': function(salary) {
  10. return salary * 2;
  11. }
  12. };
  13. // 环境函数(类)
  14. var calculateBonus = function(level, salary) {
  15. return strategies[level](salary);
  16. }
  17. console.log(calculateBonus('S', 20000)); // 输出: 80000
  18. console.log(calculateBonus('A', 10000)); // 输出: 30000

策略模式的应用——表单校验

在实际开发中,我们通常会把算法的含义扩散开来,使策略模式也可以用来封装一系列的”业务规则”,只要这些业务规则指向的目标一致,并且可以被替换,我们就可以用策略模式来封装它们。

一个广泛使用策略模式的场景就是表单校验,通常有以下几条校验规则:

  1. 输入内容不能为空;
  2. 输入字符个数不能少于指定个数;
  3. 诸如手机号等的格式校验。

最终实现代码如下:

DOM 结构:

  1. <!-- 其余代码省略 -->
  2. <form action="/" method="POST">
  3. <input id="phoneEl" name="phone" type="text" placeholder="默认内容" />
  4. <input id="submitBtn" type="submit" value="提交" />
  5. </form>

JavaScript 代码:

  1. // 策略对象(类)
  2. var strategies = {
  3. ifNonEmpty: function(value) {
  4. return value != '';
  5. },
  6. ifComplete: function(value, length) {
  7. return value.length == length;
  8. },
  9. ifMobile: function(value) {
  10. return /(^1[3|5|8][0-9]{9}$)/.test(value);
  11. }
  12. };
  13. // 环境函数(类)
  14. var bindStrategy = function(el, paramString) {
  15. var paramArray = paramString.split(':');
  16. var rule = paramArray[0];
  17. var params = paramArray.slice(1);
  18. params.unshift(el.value);
  19. return strategies[rule].apply(this, params);
  20. }
  21. var submitBtn = document.getElementById('submitBtn');
  22. var phoneField = document.getElementById('phoneEl');
  23. submitBtn.onclick = function() {
  24. // 绑定策略
  25. var ifNonEmpty = bindStrategy(phoneField, 'ifNonEmpty');
  26. var ifComplete = bindStrategy(phoneField, 'ifComplete:11');
  27. var ifMobile = bindStrategy(phoneField, 'ifMobile');
  28. console.log(
  29. 'ifNonEmpty: ' + ifNonEmpty,
  30. 'ifComplete: ' + ifComplete,
  31. 'ifMobile: ' + ifMobile
  32. );
  33. }