TypeScript 设计模式之策略模式(IKUN粉丝见面会)

123 阅读4分钟

引言

策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时选择算法的一种方法,从而在不同情境下能够更灵活地改变对象的行为。该模式的核心思想是将不同的算法封装成独立的策略类,使得这些算法可以互相替换,而客户端代码不需要知道具体使用哪种算法,从而降低了代码之间的耦合性。

Define a family of algorithms,encapsulate each one,and make them interchangeable.(定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。)

策略模式demo (IKun 粉丝见面会策略)

情景再现,IKUN 终于忙完了给每个小黑子都发了律师函,决定搞一个粉丝见面会。经纪人根据IKUN的才艺制定了三个策略:打篮球、Rap 表演、唱歌跳舞。制定好了流程,随便IKUN选择哪个策略粉丝见面会流程都能正常进行~

非常符合策略设计模式的应用场景。我们一起来看看代码实现~

// 策略抽象接口,必须要 show 一下
interface IKunFansInteractInterface {
  show(msg: string):void;
}

// IKun 粉丝见面会有三个策略

// 如果下雨,那就室内打篮球
class BasketballStrategy implements IKunFansInteractInterface {
  constructor() {
    // 初始化,穿上背带裤
  }

  show(msg: string) {
    console.log('我是 IKUN, 我为 NBA 代言~', msg);
  }
}

// 给大家表演一首 Rap 
class RapStrategy implements  IKunFansInteractInterface {
  constructor() {
    // 准备好破洞牛仔裤
  }

  show(msg: string) {
    console.log('大家跟我一起 Rap~ 嘿嚯 ~ 轰')
  }
}

// 给大家跳个舞
class DanceAndMusicStrategy implements IKunFansInteractInterface {
  show(msg: string) {
    console.log('给大家表演才艺~ 唱跳');
  }
}


class IKunContext {
  // 今天坤坤时间不够,晚上有安排了,一次只能安排一个粉丝见面会
  private strategy: IKunFansInteractInterface;

  constructor(strategy: IKunFansInteractInterface) {
    this.strategy = strategy;
  }

  // IKUN 开始表演
  public run() {
    this.strategy.show('IKUN');
  }
}

// IKUN 说了随便哪个都行,我是经纪人,别说我不公平。随机转个骰子,转到谁就是谁~
function main() {

  console.log('____________________________')

  const random = Math.random();

  // 打篮球
  if (random < 0.33) {
    const runner = new IKunContext(new BasketballStrategy());
    runner.run();

    return;
  }

  // rap
  if (random > 0.66) {
    const runner = new IKunContext(new RapStrategy());
    runner.run();
    return;
  }

  const runner = new IKunContext(new DanceAndMusicStrategy());
  runner.run();

}

main();
main();
main();

出色的完成了粉丝见面会,第二天经纪人收到了IKUN 的律师函~ 不用同情他,我们来看看策略模式的组成。

策略模式的组成

策略模式使用的就是面向对象的继承和多态机制,非常容易理解和掌握。主要有三个部分:

  • Context 封装,也就是这里的 IKunContext 。一般叫做上下文角色,封装上起到作用是承上启下,屏蔽高层模块对底层策略模块的直接访问。
  • Strategy 抽象策略。接口定义,也就是这里的 IKunFansInteractInterface。抽象策略定义策略中的规范,每个策略结构上要一致。
  • 具体的策略实现,抽象策略的具体实现。BasketballStrategy、RapStrategy、DanceAndMusicStrategy 爱坤三板斧就是具体的策略实现。

策略模式优点

  • 算法可以自由切换。每个实现自抽象策略的类,都可以对外提供自由切换的能力【IKUN 打篮球、Rap 两个策略可以随便切换,对本次的粉丝见面会没有影响。换到支付模式也一样:微信支付、支付宝支付、现金支付对于购物流程都是一致的~策略方式随便换】。
  • 扩展性好。太明显了,现在要扩展一个新的策略比较简单,扩展一个类实现抽象策略接口即可。比如 IKUN 经过一年半的练习,终于掌握了钢管舞,那就继承一下 IKunFansInteractInterface , show 函数里面给大家表演钢管舞即可。

策略模式的缺点

  • 策略类数量增多。每个策略就是一个类,复用的可能性非常小,类数量变多【所以如何控制策略的粒度就是设计中需要衡量的点~】。
  • 所有的策略类都需要对外暴露。上层模块必须知道有哪些策略类才能决定使用哪一个策略。这个和迪米特法则【不该知道的不打听~】相悖。解决方案就是与其他设计模式一同配合:工厂方法模式、代理模式或者享元模式【IKUN 下期会和大家再见面的,请期待~】。

策略模式的使用场景

  • 算法需要自由切换
  • 多个类之间只是存在算法或行为上稍有不同【其实是我们设计之前需要考虑的,复杂的判断条件,如何拆分成不同的算法策略~】
  • 需要屏蔽算法规则的场景。具体的逻辑我们可以不用管,只要告诉我支不支持微信支付,我上层调用微信支付即可,不需要知道微信支付的实现逻辑。

总结

策略模式,比较简单容易组织代码。基于解决它的缺点,通常会和工厂方法模式来实现策略类的申明,称之为混合模式~混编模式?

IKUN 到这里就要和大家说拜拜了~ 还得回家发律师函去~ 下期再见