TypeScript设计模式(14):模板方法模式

71 阅读2分钟

TypeScript中的模板方法模式

模板方法模式 (Template Method Pattern) 是一种使用应用很常见的行为型设计模式。它通过在基类中定义模板方法,子类通过覆盖特定步骤来完善具体过程。它通常用于处理有一致步骤的过程,但一些具体的步骤可以在子类中自定义。

模板方法模式的主要特点

  1. 封装固定的步骤,防止子类修改此步骤。
  2. 允许子类通过覆盖方法来自定义步骤细节。
  3. 增加代码的重用性,减少重复代码。

实现模板方法模式

我们通过一个食物制作的例子来实现模板方法模式:

abstract class FoodTemplate {
  // 模板方法
  public prepareFood(): void {
    this.prepareIngredients();
    this.cook();
    this.serve();
  }

  // 抽象方法,需要子类实现
  protected abstract prepareIngredients(): void;
  protected abstract cook(): void;
  
  // 共享方法,可选覆盖
  protected serve(): void {
    console.log("为客人装盘。");
  }
}

// 实现具体的饭菜
class Pasta extends FoodTemplate {
  protected prepareIngredients(): void {
    console.log("准备面粉和番茄酱。");
  }

  protected cook(): void {
    console.log("煮面条并配上番茄酱。");
  }
}

class FriedRice extends FoodTemplate {
  protected prepareIngredients(): void {
    console.log("准备米饭和蔬菜。");
  }

  protected cook(): void {
    console.log("炒饭配蔬菜。");
  }
}

// 使用
const pasta = new Pasta();
pasta.prepareFood();

const friedRice = new FriedRice();
friedRice.prepareFood();

进一步优化

在模板方法中,我们可以通过加入选填方法 (Hook Method),使子类可选性地覆盖部分行为。

abstract class FoodTemplateWithHook {
  public prepareFood(): void {
    this.prepareIngredients();
    this.cook();
    if (this.needSauce()) {
      this.addSauce();
    }
    this.serve();
  }

  protected abstract prepareIngredients(): void;
  protected abstract cook(): void;
  
  protected serve(): void {
    console.log("为客人装盘。");
  }

  protected needSauce(): boolean {
    return true;
  }

  protected addSauce(): void {
    console.log("加入汤汁。");
  }
}

class Noodles extends FoodTemplateWithHook {
  protected prepareIngredients(): void {
    console.log("准备鸡蛋面和蔬菜。");
  }
  
  protected cook(): void {
    console.log("煮面条。");
  }
  
  protected needSauce(): boolean {
    return false; // 这里选择不需要汤汁
  }
}

const noodles = new Noodles();
noodles.prepareFood();

结论

模板方法模式在 TypeScript 中可以通过抽象类来实现,在基类中定义模板方法,允许子类自定义特定步骤,提高代码的重用性,同时限制了子类作出不适当的修改。