美文网首页
策略模式

策略模式

作者: 小宇cool | 来源:发表于2020-11-04 21:12 被阅读0次

    1. 策略模式

    1.1 定义

    策略模式(Strategy):策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,且具有一定的独立性, 不会随客户端的变化而变化.

    一系列的算法, 可以相互醍醐, 也就是说为了同一个目的, 可能采取的算法不一样, 同时要体现出独立性.策略模式将这些算法封装成一个一个的类,可以任意的替换

    1.2 作用

    1. 减轻当代码中过多if...else带来的复杂度和难以维护的问题.
    2. 让一个对象可以动态得在许多行为中选择一种行为.
    3. 提高代码的可扩展性,让算法可以自由切换.

    1.3 应用场景

    • 场景一 根据不同的操作类型进行不同的DOM操作
    // 操作DOM元素实现动画效果
    let box = document.querySelector('.box'); 
    // 根据不同的type进行不同的DOM操作, type 操作的类型, data表示的数值
    function run(type,data){
         if(type ===  'moveY'){
             box.style.transform = `translateY(${data}px)`
         }else if(type === 'zoom'){
             box.style.transform = `scale(${data})`
         }else if(type === 'changeColor'){
             box.style.backgroundColor = data
         }else {
             box.style.opacity = data
         }
     }
    box.addEventListener('click' ,ev =>{
        run('zoom',2)
    })
    
    

    上面的代码我们通过对run函数传入不同的操作类型和对应的数值, 实现对DOM的操作, 可以看到我们写了非常多的if...else, 看起来非常臃肿, 模块之间耦合性比较强, 可扩展性不强, 当代码的分支判断语句越来越长时,代码非常难以维护, 此时我们可以利用策略模式优化一下代码.

    let box = document.querySelector('.box');   
    let Strategy = (function (){
          //利用闭包 保存所有策略和对应操作
          let s ={
              moveY(pxsize){//移动box元素在y轴上的位置
                  box.style.transform = `translateY(${pxsize}px)`
              },
              zoom(size){// 缩放box元素
                  box.style.transform = `scale(${size})`
              },
              changeColor(color){//改变box元素的背景颜色
                  box.style.backgroundColor = color
              },
              changeOpacity(size){// 改变box元素的的不透明度
                  box.style.opacity = size
              }
          };
          return {
              // 运行对应的策略
              run(type,data){
                  s[type](data)
              },
              // 添加新的策略
              addStr(type,callback){
                  s[type] = callback
              },
          }
      })();
      box.addEventListener('click', ev =>{
          Strategy.run('changeOpacity',0.78)
      });
    

    上面的代码是一个很简单的策略模式, 我们利用闭包来把所有的策略保存到对象中, 通过对应暴露两个运行策略和添加策略的接口,实现对策略的使用, run方法通过传入的type来获取对应的策略并运行对应的方法并传对应的参数, 通过addStr接口我们可以添加新的策略,提高了策略的扩展性, 较大得提高了代码的可读性.

    • 场景二
     // 玩家类
            class Player {
                constructor() {
                    // 保存消费总价
                    this.totalCost = 0;
                    //对应的消费等级
                    this.level = "C"
                }
                consume(price) {
                    // 计算消费的总价;
                    this.totalCost += price
                    let result = strategy.calc(this.level, price);
                    this.getLevel();
                    // 返回当消费的价格
                    return result
                }
                getLevel() {
                    // 设置当前消费等级
                    this.level = levelStrategy.calc(this.totalCost)
                }
            }
            // 计算level 策略类
            const levelStrategy = (function () {
                let s = [{
                        maxTotalCost: 5000,
                        level: "S"
                    },
                    {
                        maxTotalCost: 3000,
                        level: "A"
                    },
                    {
                        maxTotalCost: 2000,
                        level: "B"
                    },
                    {
                        maxTotalCost: 0,
                        level: "C"
                    }
                ];
                return {
                    // 计算当前消费所对应的等级
                    calc(totalCost) {
                        for (const v of s) {
                            if (totalCost >= v.maxTotalCost) {
                                return v.level
                            }
                        }
                    }
                }
            })()
            // 折扣策略类
            const strategy = (function () {
                let s = {
                    S(price) {
                        return price * 0.85
                    },
                    A(price) {
                        return price * 0.9;
                    },
                    B(price) {
                        return price * 0.95;
                    },
                    C(price) {
                        return price;
                    }
                };
                return {
                    addSty(name, fn) {
                        s[name] = fn
                    },
                    //计算策略所定义最终价格的接口
                    calc(sty, price) {
                        if (s[sty]) {
                            return s[sty](price)
                        } else {
                            throw new Error('对应的优惠策略不存在')
                        }
                    }
                }
            })();
            let player = new Player();
            console.log(player.consume(5000));// 5000 
            console.log(player.consume(100));// 85
    
    

    总结 : 当一个对象有多种行为, 并且需要动态的让对象在行为中选择一种行为时,此时使用策略模式就非常合适,大大地减轻了我们使用if...else所带来的复杂性和维护性.策略模式的实现就是通过把这些算法封装成一个类,然后通过指定的行为类型来获取出对应的行为并执行对应的操作,使得我们可以任意的进行替换我们想要的行为.极大提升了代码的灵活性和可扩展性.

    相关文章

      网友评论

          本文标题:策略模式

          本文链接:https://www.haomeiwen.com/subject/ytrnvktx.html