ITPub博客

首页 > 数据库 > 数据库开发技术 > 模板方法模式--我们一起下饺子

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

原创 数据库开发技术 作者:zhanyd 时间:2020-06-08 08:55:00 0 删除 编辑

饺子制作的过程


小帅在外奔波多年,厌倦了程序员的生活,终于决定回老家安定下来,开了个饺子馆,天天下饺子。
小帅跟一个大厨苦练饺子制作,自己总结了一下饺子制作的过程:
擀面皮
包馅
水煮
出锅
加基本调料
加其他调料(顾客自行添加)
小帅就以这个流程为模板,在店里做各种各样的饺子,恩,生意还挺好的。

普通方法做饺子

小帅发挥程序员的特长,把做饺子的经过用代码写了下来,其实很简单:
制作韭菜馅饺子
/*** 韭菜馅饺子*/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() {  }}

制作猪肉馅饺子
/*** 猪肉馅饺子*/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("加重辣");  }}

小帅的店里不仅有韭菜馅饺子,猪肉馅饺子还有牛肉馅,蘑菇馅,海鲜馅饺子等等十几种呢。
各种饺子的制作过程其实都是大同小异,主要是包的馅不一样,然后就水煮的时间不一样。
如果每种饺子都各自实现一次所有的代码,会出现大量的重复代码,该怎么改进呢?

模板方法做饺子


其实每种饺子的制作都是按固定的流程制作的,这种情况就非常适合使用模板方法模式。
模板方法模式定义如下:模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
类图如下:
按照模板方法模式改造一下:
饺子抽象类
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() {  }}

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

猪肉馅饺子
/*** 猪肉馅饺子*/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("加重辣");  }}

制作饺子
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();}}
输出结果
制作韭菜馅饺子擀面皮包韭菜馅水煮8分钟出锅加醋
制作猪肉馅饺子擀面皮包猪肉馅水煮10分钟出锅加醋加重辣

饺子的固定制作过程,擀面皮【ganMianPi()】,出锅【chuGuo()】, 加基本调料【jiaJiBenTiaoLiao()】每种饺子都是一样的,所以直接在父类中实现,实现了代码的复用。
包馅【baoXian()】,水煮【shuiZhu()】每种饺子都不一样,定义为抽象方法,具体的操作推迟到子类中实现。
钩子【hook()】方法比较有意思,在父类中默认实现为空,如果子类有什么特殊的操作,父类中没有定义的,那么子类就可以覆盖hook(),实现自己扩展的业务逻辑。
比如加辣椒,不是每个客人都喜欢吃辣的,那么需要加辣椒的顾客自己覆盖hook()方法,加上辣椒就行了,不需要加辣椒的顾客就不用重写hook()方法了。

总结


在模板模式经典的实现中,模板方法定义为 final,可以避免被子类重写。
需要子类重写的方法定义为 abstract,可以强迫子类去实现。
如果子类需要扩展,可以预留一个hook()的空实现方法,让需要的子类去重写。
该模式应用了好莱坞原则:别调用(打电话给)我们,我们会调用(打电话给)你。
换句话说就是:子类你别调用我们(父类),我们(父类)会调用你。
模板模式有两大作用:复用和扩展。
复用指的是,所有的子类可以复用父类中提供的模板方法的代码。
扩展指的是,框架通过模板模式提供功能扩展点,也就是钩子hook(),让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。
(公众号回复:设计模式代码,获取git代码链接)
















原文作者:编程我也会;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2018-06-20

  • 博文量
    120
  • 访问量
    51702