js设计模式---策略模式

87 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情

策略模式的定义

  • 将定义的一组算法封装起来,使其相互之间可以替换。封装的算法具有一定独立性,不会随客户端变化而变化
  • 避免大量的if else或switch case 举个例子,不同类别的顾客(普通顾客/会员顾客/vip顾客)打折情况不同,会员顾客打九折,vip顾客打八折,普通顾客原价。

类图

image.png image.png

代码

不考虑使用设计模式,简单实现如下:

class Customer(){
  constructor(type){
     this.type = type;
  }
  pay(amount){
     if(this.type == 'member'){
       return amount*.9;
     }
     else if(this.type == 'vip'){
       return amount*.8;
     }
     else{
       return amount;
     }
  }
}
let c = new Customer('normal');
console.log(c.pay(100));

缺陷:

  • pay逻辑复杂
  • 很多if else 那么要如何改进呢?可以考虑使用策略模式:定义多个不同的策略类,再调用不同的策略类即可。这样写就不会再出现大量的if/else,而且pay方法的逻辑也简单了许多。
class Customer(){
  constructor(kind){
     this.kind = 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;}
}
let c1 = new Customer(new Normal());
console.log(c1.pay(100));
c1.kind = new Member;
console.log(c1.pay(100));

也可以使用以下写法,也同样运用了策略模式:在类里面定义几种算法,然后在pay中调用指定算法即可

class Customer(){
  constructor(kind){
     this.kinds = {
       normal:function(amount){return amount;},
       member:function(amount){return amount*.9;},
       vip:function(amount){return amount*.8;}
     };
  }
  pay(kind,amount){
     return this.kind[kind](amount);
}
let c2 = new Customer();
console.log(c2.pay('normal',100));

总结而言,就是给不同的类型,策略,调不同的方法。

应用场景

  • form表单不同的校验规则策略
  • animate
    • animater()方法执行css属性集的自定义动画
    • 该方法通过css样式将元素从一个状态改变为另一个状态。

策略模式和状态模式的区别

  • 策略模式和状态模式都有上下文,有策略类或者状态类,上下文把这些请求委托给这些类来执行
  • 策略模式中各个类是平等的,没有关系,客户端需要知道算法主动切换,状态模式中,状态的切换和行为需要了解细节。