设计模式之策略模式

类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式

策略模式中, 创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法

策略模式的优点

  • 算法(功能)可以自由切换
  • 避免使用多重条件判断
  • 扩展性好

策略模式的缺点

  • 策略类会增多
  • 所有的策略都会暴露在外部

代码

这里是按照超市支付的角色为模型创建,有四个策略,普通顾客,熟客,会员,老板等,在支付的时候使用不同的策略

  • 策略内置实现
class Customer{
  // 第一策略
  kinds = {
    // 普通用户
    normal: {
      pay(amount) {
        return amount
      }
    },
    // 会员
    member: {
      pay(amount) {
        return amount * .9
      }
    },
    // VIP
    vip: {
      pay(amount) {
        return amount * .8
      }
    }
  }
  /**
   * @des 暴露扩展策略接口
   * @param { Sting } kind 策略类型的名字
   * @param { Object } obj 策略对象
   */
  addKind(kind, obj) {
    this.kinds[kind] = obj
  }
  // 统一暴露的支付方法
  pay(kind, amount) {
    return this.kinds[kind].pay(amount)
  }
}

// 调用
let c = new Customer()
// 使用普通支付
console.log(c.pay('normal', 100))
// 使用会员支付
console.log(c.pay('member', 100))
// 使用VIP身份支付
console.log(c.pay('vip', 100))

// 新增老板模式
c.addKind('boss', {
  pay(amount) {
    return 0
  }
})

// 使用老板模式i支付
console.log(c.pay('boss', 100))
  • 策略外置实现
// 策略外置写法
class Customer {
  constructor(Kind) {
    this.kind = new Kind()
  }
  // 对外暴露方法
  pay(amount) {
    return this.kind.pay(amount)
  }
}
// 定义策略
class Normal{
  pay(amount) {
    return amount
  }
}

class Member{
  pay(amount) {
    return amount * .9
  }
}
class VIP{
  pay(amount) {
    return amount * .8
  }
}
class Boss{
  pay(amount) {
    return 0
  }
}

// 普通会员
let c1 = new Customer(Normal)
console.log(c1.pay(100))
// 会员
let c2 = new Customer(Member)
console.log(c2.pay(100))

// vip
let c3 = new Customer(VIP)
console.log(c3.pay(100))

// Boss
let c4 = new Customer(Boss)
console.log(c4.pay(100))

使用场景

  • 表单验证

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    
      <title>策略模式之表单验证</title>
      <style>
        .container{
          padding-top: 200px;
        }
        .line{
          margin-bottom: 12px;
        }
      </style>
    </head>
    <body>
      <div class="container">
        <form id="form">
          <div class="line">
            账&emsp;号: <input type="text" name="name" id="name">
          </div>
          <div class="line">
            密&emsp;码: <input type="password" name="password" id="password">
          </div>
          <div class="line">
            验证码: <input type="vertiry" name="vertiry" id="vertiry">
          </div>
          <div class='line'>
            <button type="button" class="btn btn-primary" id="submit">提交</button>
          </div>
        </form>
      </div>
       <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
       <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
       <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
       <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
       <script>
         class Validate {
           roules = {
             empty: (val, msg) => {
              //  判断是否为空
               if (!val) return msg
             },
             minLength: (val, len, msg) => {
              //  检查对小长度
               if (!val || val.length < len) return msg
             },
             maxLength: (val, len, msg) => {
              //  检查最大长度
               if (!val || val.length > len) return msg
             },
             isNumber: (val, msg) => {
              //  判断是否为纯数字
               let reg = /^[0-9]*$/g;
               if (!reg.test(val)) return msg
             }
           }
          //  检测函数回调
          callbacks = []
          // 添加函数
          add(el, val) {
            this.callbacks.push(() => {
              let key = val[0]
              let value = el.value
              return this.roules[key].apply(this, [value, ...val.slice(1)])
            })
          }
          /**
           * @desc 添加规则
           * 
           */
          addRoule(roule, fn) {
            this.roules[roule] = fn
          }
          /**
           * @desc 验证
           * 
           */
          vertify() {
            let msg = ''
            let { callbacks } = this
            for (let i = 0, len = callbacks.length; i < len; i++) {
              let fn = callbacks[i]
              msg = fn()
              // 如果有msg 说明校验不通过
              if (msg) {
                return msg
              }
            }
          }
         }
         //  添加长度等于规则
         
    
         let form = document.querySelector('#form')
         let btn = document.querySelector('#submit')
         let validate = new Validate()
         validate.addRoule('equlLength', (val, len, msg) => {
           if (!val || val.length !== len) return msg
         })
        //  添加验证规则
        validate.add(form.name, ['empty', '用户名不能为空'])
        validate.add(form.password, ['empty', '密码不能为空'])
        validate.add(form.password, ['minLength', 6, '密码不能少于6位'])
        validate.add(form.password, ['maxLength', 8, '密码不能大于8位'])
        validate.add(form.vertiry, ['empty', '验证码不能为空'])
        validate.add(form.vertiry, ['isNumber', '验证码必须为数字'])
        validate.add(form.vertiry, ['equlLength', 4, '验证码为4为数字'])
         btn.addEventListener('click', () => {
          
          
          let res =  validate.vertify()
          if (res) {
            alert(res)
            return false
          }
         })
       </script>
    </body>
    </html>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值