• 设计模式中的模板方法模式
  • 发布于 2个月前
  • 172 热度
    0 评论
  • 小熊
  • 0 粉丝 30 篇博客
  •   
概念
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤

结构
抽象类
.负责一个算法的轮廓和骨架,由一个模板方法和若干个基本方法构成
.模板方法:定义了算法的骨架,按照某种顺序调用其包含的基本方法

.基本方法:由抽象方法(抽象类声明、具体子类实现)、具体方法(抽象类或具体子类声明并实现,具体子类可以覆盖或直接继承)、钩子方法(抽象类中已声明并实现)组成


具体子类
实现抽象类中所定义的抽象方法和钩子方法,是一个顶级逻辑的组成步骤

示例
目标:实现一个炒菜的逻辑:倒油 -> 放菜 -> 加调料 -> 翻炒

抽象类
package 设计模式.行为型模式.模板方法模式;
/**
 * 堆代码 duidaima.com
 * 炒菜:抽象类
 */
public abstract class StirFry {

  /**
   * 模板方法
   *
   * 注意:需要使用final修饰,不允许被子类重写
   */
  public final void start() {
    // 倒油
    this.pourOil();
    // 加菜
    this.addFood();
    // 加调味料
    this.addSauce();
    // 翻炒
    this.fry();
  }

  /**
   * 倒油
   */
  private void pourOil() {
    System.out.println("倒油");
  }

  /**
   * 加菜
   */
  abstract void addFood();

  /**
   * 加调味料
   */
  abstract void addSauce();

  /**
   * 翻炒
   */
  private void fry() {
    System.out.println("翻炒");
  }

}
具体子类
package 设计模式.行为型模式.模板方法模式;
/**
 * 青椒炒肉
 */
class GreenPepperFriedMeat extends StirFry {

  /**
   * 加菜
   */
  @Override
  void addFood() {
    System.out.println("放入五花肉");
  }

  /**
   * 加调味料
   */
  @Override
  void addSauce() {
    System.out.println("放入青椒");
  }

}
测试类
package 设计模式.行为型模式.模板方法模式;
public class Demo {

  public static void main(String[] args) {
    // 创建实例对象
    GreenPepperFriedMeat gpfm = new GreenPepperFriedMeat();
    // 调用模板方法
    gpfm.start();
  }

}
优缺点
优点
1.提高了代码的复用性。将相同的代码放在抽象的父类中,将不同的代码放在不同的子类中
2.实现了反向控制。通过父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制,并符合“开闭原则”

缺点
1.对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大、设计也更多抽象
2.父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,增加了代码的阅读难度

应用场景
1.算法的整体步骤很固定,但其中个别部分易变时,可以使用模板方法模式
2.需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制
用户评论