# 设计模式:策略模式

# 什么是策略模式

定义一系列算法,把他们一个个封装起来,并且可以相互替换。

# 使用场景

比如表单验证这个场景就非常合适,每一个验证规则都是一个算法。比如邮箱验证,字符串长短验证。 我们可以定义一套算法函数,然后针对每个字段的应用场景来调用甚至组合调用。

还有 css动画的运动曲线 ease ease-in ease-in-out 每种运动曲线都可以随意替换,这就是典型的策略模式。

# Coding

if 条件分支写法

  • 用户名不能为空。
  • 密码长度不能少于 6 位。
  • 手机号码必须符合格式。
// 提交代码函数
fromDom.onsubmit = function() {
  // 用户名验证
  if (fromDom.username.value === '') {
    alert('用户名不能为空');
    return false;
  }
  if (fromDom.username.value.length > 8) {
    alert('用户长度必须大于8位');
    return false;
  }
  // 密码验证
  if (fromDom.password.value.length > 8) {
    alert('密码长度必须大于8位');
    return false;
  }
  // 手机号码验证
  if (!/(^1[3|5|8][0-9]{9}$)/.test(fromDom.phone.value)) {
    alert('请输入有效的手机号码');
    return false;
  }
  alert('验证通过');
}

策略模式写法

// 策略对象
const strategies = {
  isNonEmpty: function(val, errMsg) {
    if (val === '') {
      return errMsg;
    }
  },
  minLength: function(val, errMsg, length,) {
    if (val.length < length) {
      return errMsg;
    }
  },
  isMobile: function(val, errMsg) {
    var res = !/(^1[3|5|8][0-9]{9}$)/.test(val)
    if (res) {
      return errMsg;
    }
  }
}
// 校验对象
var Validateor = function() {
  this.cache = [];
}
Validateor.prototype.add = function(value, rules) {
  var self = this;
  for (var i = 0, rule; rule = rules[i++];) {
    ;(function(rule) {
      console.log(
        rule
      )
      self.cache.push(function() {
        return strategies[rule.action](value, rule.errMsg, rule.length)
      })
    })(rule);
  }
}

Validateor.prototype.start = function() {
  for (var i = 0, validateorFn; validateorFn = this.cache[i++];) {
    var errMsg = validateorFn();
    if (errMsg) {
      return errMsg;
    }
  }
}

var fromDom = document.getElementById('form')

var validateorFn = function() {
  var validateor = new Validateor();
  validateor.add(fromDom.username.value, [
    {
      action: 'isNonEmpty',
      errMsg: '用户名不能为空'
    },
    {
      action: 'minLength',
      length: 8,
      errMsg: '用户名长度不能少于8位'
    }
  ])

  validateor.add(fromDom.password.value, [
    {
      action: 'minLength',
      length: 8,
      errMsg: '密码长度不能少于8位'
    }
  ])

  validateor.add(fromDom.phone.value,[
    {
      action: 'isMobile',
      errMsg: '请输入正确的手机号码'
    }
  ])

  let errMsg = validateor.start();
  return errMsg;
}
// 提交代码函数
fromDom.onsubmit = function() {
  var errMsg = validateorFn();
  if (errMsg) {
    alert(errMsg);
  }
  alert('验证通过')
}

通过使用策略模式重构代码,我们消除了原程序中大片的条件分支语句。并且这样的代码可以很方便的实现功能扩展。

# 总结

  • 策略模式是利用组合,委托,多态的思想。有效的避免了多重条件分支语句。
  • 利于扩展,在 strategies 对象中可以任意新增功能。调用相应的算法时只需给定相应的配置即可。
上次更新: 9/7/2020, 12:02:51 PM