javascript策略模式

     策略模式的定义是:定义一系列的算法,把它们都封装起来,并使它们可以互相替换。
     实例一:使用策略模式计算奖金
     很多公司的年终奖是根据员工的工资基数和年底绩效情况来发放的。例如,绩效为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;
         }
     }

     calculateBonus('B',2000); // 输出:4000
     calculateBonus('s',5000); // 输出:20000

     上面的代码非常简单,但有很明显的缺点。
     1.calculateBonus函数也许会非常庞大,那会包含很多if-else语句
     2.calculateBonus函数缺乏弹性,如果增加一种新的绩效,或者想修改绩效,那就必须得深入calculateBonus函数内部实现,这是违反开放-封闭原则的。
     3.算法的复用性差,如果要在程序的其它地方重用这些代码,就只能复制和粘贴。

     所以这段代码需要重构。

     使用组合函数重构代码:
     var performanceS = function(salary){
          return salary * 4;
     }
     var performanceA = function(salary){
          return salary * 3;
     }
     var performanceB = function(salary){
          return salary * 2;
     }

     var calculateBonus = function(performanceLevel, salary){
          if(performanceLevel == 'S'){
               return performanceS(salary);
          }
          if(performanceLevel == 'A'){
               return performanceA(salary);
          }
          if(performanceLevel == 'B'){
               return performanceB(salary);
          }
      }

      calculateBonus('s',5000); // 输出:20000


      使用策略模式重构代码:
      一个基于策略模式的程序至少由两部分组成。第一部分是一组策略类,封装了具体的算法,负责具体的计算过程。第二部分是环境类Context,Context接受客户的请求,随后委托给某一个策略类(要做到这点,说明Context要维持对某个策略对象的引用)。下面是模仿传统面向对象语言中的实现:
      var performanceS = function(){}
      performanceS.prototype.calculate = function(salary){
           return salary * 4;
      }
      var performanceA = function(){}
      performanceA.prototype.calculate = function(salary){
           return salary * 3;
      }
      var performanceB = function(){}
      performanceB.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(stratege){
            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

      javascript版本的策略模式:
      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 );
       };

       console.log( calculateBonus( 'S' , 15000 ) ); // 输出 60000

 

 

 

      策略模式的优缺点:
      1.策略模式利用组合、委托和多态等技术思想,可以有效地避免多重条件选择语句
      2.策略模式提供了对开放-封闭原则的支持,将算法封装在独立的对象中,这样易于切换、易于理解、易于理解
      3.在策略模式中,可以将算法复用在程序的其它地方,避免复制粘贴代码
      4.在粗略模式中利用组合和委托来让Context拥有执行算法的能力,这也是继承的一种更轻便的替代方案

      缺点:
      首先,使用策略模式会在程序中增加许多策略类或者策略对象(但实际上这比把它们负责的逻辑放在Context中要好)。
      其次,要使用策略模式,就得了解策略模式中所有的选项,此时就必须要向客户暴露策略类的所有实现,这就违反了最少知识原则

 

posted @ 2016-08-25 15:58  西风.烈马  阅读(126)  评论(0编辑  收藏  举报