zl程序教程

您现在的位置是:首页 >  Java

当前栏目

?【设计模式】模板方法模式

2023-02-18 16:41:30 时间

在面向对象编程的过程中我们常提到重构,将一些重复的代码进行提取封装等,因为重复的代码在一定程度上会造成在编码中容易出错,在编码后难以维护。 ​

同学们手抄试题:

我们通过使用原始的方法来抄两份试题交给老师

手抄试卷01

class Paper01 {
  constructor() {
    console.log("==========试卷01==========");
  }

  question1(): void {
    console.log("题目01: 窗前明月光,下一句?");
    console.log("答案: ", "疑似地上霜");
  }

  question2(): void {
    console.log("题目02: 鹅鹅鹅,下一句?");
    console.log("答案: ", "曲项向天歌");
  }

  question3(): void {
    console.log("题目02: 长风破浪会有时,下一句?");
    console.log("答案: ", "直挂云帆济沧海");
  }
}

手抄试卷02

class Paper02 {
  constructor() {
    console.log("==========试卷02==========");
  }
  question1(): void {
    console.log("题目01: 窗前明月光,下一句?");
    console.log("答案: ", "疑似地上霜");
  }
  question2(): void {
    console.log("题目02: 鹅鹅鹅,下一句?");
    console.log("答案: ", "曲项向天歌");
  }
  question3(): void {
    console.log("题目03: 臣心一片磁针石,下一句?");
    console.log("答案: ", "不指南方不肯休");
  }
}

上交答案

const paper01 = new Paper01();
paper01.question1();
paper01.question2();
paper01.question3();
const paper02 = new Paper02();
paper02.question1();
paper02.question2();
paper02.question3();

说明

上面的实践可以看出,试卷02中的第三题似乎抄错了,并且两份试卷除了答案会有差异外,题目应该是一致的才是,老师要是需要修改题目的话每个同学又需要一起重抄一遍。

老师准备了一份试卷

老师为我们准了的试卷有助于我们题目的统一

试卷模板

class PaperBase {
  question1(): void {
    console.log("题目01: 窗前明月光,下一句?");
  }

  question2(): void {
    console.log("题目02: 鹅鹅鹅,下一句?");
  }

  question3(): void {
    console.log("题目02: 长风破浪会有时,下一句?");
  }
}

改造试卷01和02

// 试卷02同试卷01
class Paper01 extends PaperBase {
  constructor() {
    super();
    console.log("==========试卷01==========");
  }

  question1(): void {
    super.question1();
    console.log("答案: ", "疑似地上霜");
  }

  question2(): void {
    super.question2();
    console.log("答案: ", "曲项向天歌");
  }

  question3(): void {
    super.question3();
    console.log("答案: ", "直挂云帆济沧海");
  }
}

说明

通过将试卷01和02共同继承自Base版本,解决了我们题目容易出错的现象,但是在我们的试卷01和02中还是有很多重复的内容同样可以提取到父类中,使得我们的子类中只保留不通的地方,充分的利用我们的父类。

引入模板方法模式

当我们要完成某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模板方法模式来处理。--【大话设计模式】94页

基础试卷2.0

abstract class PaperBase {
  question1(): void {
    console.log("题目01: 窗前明月光,下一句?");
    console.log("答案: ", this.answer1());
  }

  question2(): void {
    console.log("题目02: 鹅鹅鹅,下一句?");
    console.log("答案: ", this.answer2());
  }

  question3(): void {
    console.log("题目02: 长风破浪会有时,下一句?");
    console.log("答案: ", this.answer3());
  }

  abstract answer1(): string;
  abstract answer2(): string;
  abstract answer3(): string;
}

再次改造试卷01和02

class Paper01 extends PaperBase {
  answer1(): string {
    return "疑似地上霜";
  }
  answer2(): string {
    return "曲项向天歌";
  }
  answer3(): string {
    return "直挂云帆济沧海";
  }
}

说明

通过模板方法模式使得我们的试卷01和02就只剩下了各自的答案,完成了又一次改造。

模板方法模式

定义一个操作中的算法骨架,将一些步骤延迟到子类。模板方法使得子类可以实现不改变算法结构即可重新定义该算法的特定步骤。