首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >模板方法模式--我们一起下饺子

模板方法模式--我们一起下饺子

作者头像
zhanyd
发布2022-05-16 13:38:54
发布2022-05-16 13:38:54
2610
举报
文章被收录于专栏:编程我也会编程我也会

饺子制作的过程 小帅在外奔波多年,厌倦了程序员的生活,终于决定回老家安定下来,开了个饺子馆,天天下饺子。

小帅跟一个大厨苦练饺子制作,自己总结了一下饺子制作的过程:

擀面皮 包馅 水煮 出锅 加基本调料 加其他调料(顾客自行添加)

小帅就以这个流程为模板,在店里做各种各样的饺子,恩,生意还挺好的。

普通方法做饺子

小帅发挥程序员的特长,把做饺子的经过用代码写了下来,其实很简单:

制作韭菜馅饺子

代码语言:javascript
复制
/**
* 韭菜馅饺子
*/
public class LeekDumpling {    
   /**
   * 做饺子
   */
  public void makeDumpling() {        
      // 擀面皮
      ganMianPi();        
      // 包馅
      baoXian();        
      // 水煮
      shuiZhu();        
      // 出锅
      chuGuo();        
      // 加基本调料
      jiaJiBenTiaoLiao();        
      // 加其他调料
      jiaQiTaTiaoLiao();
  }    
  // 擀面皮
  public void ganMianPi() {
      System.out.println("擀面皮");
  }    
  // 包馅
  public void baoXian() {
      System.out.println("包韭菜馅");
  }    
  // 水煮
  public void shuiZhu() {
      System.out.println("水煮8分钟");
  }    
  // 出锅
  public void chuGuo() {
      System.out.println("出锅");
  }    
  // 加基本调料
  public void jiaJiBenTiaoLiao() {
      System.out.println("加醋");
  }    
  // 加其他调料
  public void jiaQiTaTiaoLiao() {
  }
}

制作猪肉馅饺子

代码语言:javascript
复制
/**
* 猪肉馅饺子
*/
publicclass PorkDumpling {    
   /**
   * 做饺子
   */
  public void makeDumpling() {        
      // 擀面皮
      ganMianPi();        
      // 包馅
      baoXian();        
      // 水煮
      shuiZhu();        
      // 出锅
      chuGuo();        
      // 加基本调料
      jiaJiBenTiaoLiao();        
      // 加其他调料
      jiaQiTaTiaoLiao();
  }    
  // 擀面皮
  public void ganMianPi() {
      System.out.println("擀面皮");
  }   
    // 包馅
  public void baoXian() {
      System.out.println("包猪肉馅");
  }    
  // 水煮
  public void shuiZhu() {
      System.out.println("水煮10分钟");
  }    
  // 出锅
  public void chuGuo() {
      System.out.println("出锅");
  }    
  // 加基本调料
  public void jiaJiBenTiaoLiao() {
      System.out.println("加醋");
  }    
  // 加其他调料
  public void jiaQiTaTiaoLiao() {
      System.out.println("加重辣");
  }
}

小帅的店里不仅有韭菜馅饺子,猪肉馅饺子还有牛肉馅,蘑菇馅,海鲜馅饺子等等十几种呢。

各种饺子的制作过程其实都是大同小异,主要是包的馅不一样,然后就水煮的时间不一样。

如果每种饺子都各自实现一次所有的代码,会出现大量的重复代码,该怎么改进呢?

模板方法做饺子

其实每种饺子的制作都是按固定的流程制作的,这种情况就非常适合使用模板方法模式。

模板方法模式定义如下:模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。

类图如下:

按照模板方法模式改造一下:

饺子抽象类

代码语言:javascript
复制
public abstract class Dumpling {    
   /**
   * 做饺子
   */
  public final void makeDumpling() {        
      // 擀面皮
      ganMianPi();        
      // 包馅
      baoXian();        
      // 水煮
      shuiZhu();        
      // 出锅
      chuGuo();        
      // 加基本调料
      jiaJiBenTiaoLiao();        
      // 钩子
      hook();
  }    
  
  /**
   * 擀面皮
   */
  public void ganMianPi() {
      System.out.println("擀面皮");
  }    
  
  /**
   * 包馅(抽象方法需要在子类中实现)
   */
  public abstract void baoXian();    
  
  /**
   * 水煮(抽象方法需要在子类中实现)
   */
  public abstract void shuiZhu();    
  
  /**
   * 出锅
   */
  public void chuGuo() {
      System.out.println("出锅");
  }    
  
  /**
   * 加基本调料
   */
  public void jiaJiBenTiaoLiao() {
      System.out.println("加醋");
  }   
  
  /**
   * 钩子(自定义扩展方法,默认实现为空)
   */
  public void hook() {
  }
}

韭菜馅饺子

代码语言:javascript
复制
/**
* 韭菜馅饺子
*/
publicclass LeekDumpling extends Dumpling{    
   /**
   * 包馅
   */
  @Override
  public void baoXian() {
      System.out.println("包韭菜馅");
  }    
  /**
   * 水煮
   */
  @Override
  public void shuiZhu() {
      System.out.println("水煮8分钟");
  }
}

猪肉馅饺子

代码语言:javascript
复制
/**
* 猪肉馅饺子
*/
publicclass PorkDumpling extends Dumpling{    
   /**
   * 包馅
   */
  @Override
  public void baoXian() {
      System.out.println("包猪肉馅");
  }    
  /**
   * 水煮
   */
  @Override
  public void shuiZhu() {
      System.out.println("水煮10分钟");
  }    
  /**
   * 覆盖hook()方法,加其他调料
   */
  @Override
  public void hook() {
      System.out.println("加重辣");
  }
}

制作饺子

代码语言:javascript
复制
public class MakeDumpling {    
public static void main(String[] args) {        
    // 制作韭菜馅饺子
    System.out.println("制作韭菜馅饺子");
    LeekDumpling leekDumpling = new LeekDumpling();
    leekDumpling.makeDumpling();

    System.out.println();        
    // 制作猪肉馅饺子
    System.out.println("制作猪肉馅饺子");
    PorkDumpling porkDumpling = new PorkDumpling();
    porkDumpling.makeDumpling();
}
}

输出结果

代码语言:javascript
复制
制作韭菜馅饺子
擀面皮
包韭菜馅
水煮8分钟
出锅
加醋

制作猪肉馅饺子
擀面皮
包猪肉馅
水煮10分钟
出锅
加醋
加重辣

饺子的固定制作过程,擀面皮【ganMianPi()】,出锅【chuGuo()】, 加基本调料【jiaJiBenTiaoLiao()】每种饺子都是一样的,所以直接在父类中实现,实现了代码的复用。

包馅【baoXian()】,水煮【shuiZhu()】每种饺子都不一样,定义为抽象方法,具体的操作推迟到子类中实现。

钩子【hook()】方法比较有意思,在父类中默认实现为空,如果子类有什么特殊的操作,父类中没有定义的,那么子类就可以覆盖hook(),实现自己扩展的业务逻辑。

比如加辣椒,不是每个客人都喜欢吃辣的,那么需要加辣椒的顾客自己覆盖hook()方法,加上辣椒就行了,不需要加辣椒的顾客就不用重写hook()方法了。

总结

在模板模式经典的实现中,模板方法定义为 final,可以避免被子类重写。

需要子类重写的方法定义为 abstract,可以强迫子类去实现。

如果子类需要扩展,可以预留一个hook()的空实现方法,让需要的子类去重写。

该模式应用了好莱坞原则:别调用(打电话给)我们,我们会调用(打电话给)你

换句话说就是:子类你别调用我们(父类),我们(父类)会调用你。

模板模式有两大作用:复用和扩展

复用指的是,所有的子类可以复用父类中提供的模板方法的代码。

扩展指的是,框架通过模板模式提供功能扩展点,也就是钩子hook(),让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程我也会 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档