【第五章】策略模式

策略模式

比如要实现某一个功能有多种方案可以选择。比如压缩文件的程序,既可以选择zip算法,也可以选择gzip算法

定义: 定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换

  • 策略模式的优缺点
    优点:

      1. 策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句。
      2. 策略模式提供了对开放—封闭原则的完美支持,将算法封装在独立的 strategy 中,使得它们易于切换,易于理解,易于扩展。
      3. 策略模式中的算法也可以复用在系统的其他地方,从而避免许多重复的复制粘贴工作。
      4. 在策略模式中利用组合和委托来让 Context 拥有执行算法的能力,这也是继承的一种更轻便的替代方案。

    缺点:

      1. 使用策略模式会在程序中增加许多策略类或者策略对象,但实际上这比把它们负责的逻辑堆砌在 Context 中要好
      2. 要使用策略模式,必须了解所有的 strategy,必须了解各个 strategy 之间的不同点,这样才能选择一个合适的 strategy。
    • 使用策略模式计算奖金

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      /*
      绩效为 S 的人年终奖有 4 倍工资,绩效为 A 的人年终奖有 3 倍工资,而绩效为 B 的人年终奖是 2 倍工资。假设财务部要求我们提供一段代码,来方便他们计算员工的年终奖
      */

      //最初代码实现
      var calculateBonus = function(performanceLevel,salary){
      if(performanceLevel === 'S')return salary*4
      if(performanceLevel === 'A')return salary*3
      if(performanceLevel === 'B')return salary*2
      }
      caculateBonus('B',2000) //输出 4000
      /*

      缺点:
      1. calculateBonus 函数比较庞大,包含了很多 if-else 语句,这些语句需要覆盖所有的逻辑分支。
      2. calculateBonus 函数缺乏弹性,如果增加了一种新的绩效等级 C,或者想把绩效 S 的奖金系数改为 5,那我们必须深入 calculateBonus 函数的内部实现,这是违反开放-封闭原则的。
      3. 算法的复用性差,如果在程序的其他地方需要重用这些计算奖金的算法呢?我们的选择只有复制和粘贴。

      */

      //使用策略模式重构代码
      //目的: 算法的使用与算法的实现分离
      var perfromanceS = function(){}
      perfromanceS.prototype.calculate = function( salary ){
      return salary*4
      }

      var perfromanceA = function(){}
      perfromanceA.prototype.calculate = function( salary ){
      return salary*3
      }

      var perfromanceB = function(){}
      perfromanceB.prototype.calculate = function( salary ){
      return salary*2
      }

      //奖金类
      var Bonus = function(){
      this.salary = null //原始工资
      this.strategy = null //绩效等级对应的策略对象
      }
      Bonus.prototype.setSalary = function(salary){
      this.salary = salary //设置员工的原始工资
      }
      Bonus.prototype.setStrategy = function(strategy){
      this.strategy = strategy
      }
      Bonus.prototype.getBonus = function(){
      return this.strategy.calculate(this.salary) //把计算奖金的操作委托给对应的策略对象
      }
      var bonus = new Bonus();
      bonus.setSalary( 10000 );
      bonus.setStrategy( new performanceS() ); // 设置策略对象
      console.log( bonus.getBonus() ); // 输出:40000
      bonus.setStrategy( new performanceA() ); // 设置策略对象
      console.log( bonus.getBonus() ); // 输出:30000
    • JavaScript版本的策略模式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      /*
      我们让 strategy 对象从各个策略类中创建而来,这是模拟一些传统面向对象语言的实现。实际上在 JavaScript 语言中,函数也是对象,所以更简单和直接的做法是把 strategy直接定义为函数:
      */
      //策略对象
      var strategies = {
      "S": function( salary ){
      return salary*4
      },
      "A": function( salary ){
      return salary*3
      },
      "B": function( salary ){
      return salary*2
      }
      }
      //操作类
      var calculateBonus = function(level,salary){
      return strategies[level](salary)
      }
      calculateBonus('S',200) //800

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2019-2023 John Doe
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信