> 文章列表 > 设计模式之模版方法

设计模式之模版方法

设计模式之模版方法

往期文章

  • springcloud整合knike4j聚合微服务接口文档
  • spring源码 - 条件注解@ConditionnalOnClass的原理分析
  • springboot项目实现导出pdf功能,这也太简单了吧

    文章目录

    • 往期文章
    • 一、介绍
    • 二、入门示例
    • 三、实践
    • 四、使用场景
    • 五、总结

一、介绍

模版方法是23种设计模式中的一个,属于行为性设计模式。是对算法行为方式的一类设计。

所谓模版方法,就是在一个方法中,定义了一系列其他方法的调用顺序,而其他方法由各个子类实现。因此当调用这个方法时,它只提供了其他方法的调用顺序,其他方法的实现细节由调用方的实际类型决定。

简单理解就是定义一个模版,模版内的不同模块该如何实现交给子类完成。

打个比方,你是两个孩子(孩子A和孩子B)的爸爸,你给他们提出了一日三餐的规定,先吃早饭,再吃午饭,最后吃晚饭。

两个孩子很乖

  • 孩子A早饭喝粥,午饭吃饭,晚饭吃屎
  • 孩子B早饭吃包子,午饭吃面,晚饭喝尿

他们爱吃什么吃什么,这是他们的吃饭自由,反正实现了一日三餐的规定。

二、入门示例

下面我们用代码来描述模版方法的思想。

父类A定义了一个模版方法:一日三餐,以及另外三个方法:早饭、午饭、晚饭。其子类B和C分别对这三个方法进行重写来实现各自的逻辑。当这两个子类的对象调用继承自父类A的一日三餐时,就会按顺序对早饭、午饭、晚饭三个方法进行调用。代码如下

  • 定义一日三餐模版的父亲类

    public class Parent {// 一日三餐的模版public void threeMealsDaily() {// 早饭breakfast();// 午饭lunch();// 晚饭dinner();}// 早饭public void breakfast() {}// 午饭public void lunch() {}// 晚饭public void dinner() {}
    }
    
  • 儿子

    public class Son extends Parent{// 早饭@Overridepublic void breakfast() {System.out.println("早饭:喝粥");}// 午饭@Overridepublic void lunch() {System.out.println("午饭:米饭");}// 晚饭@Overridepublic void dinner() {System.out.println("晚饭:吃屎");}
    }
    
  • 女儿

    public class Daughter extends Parent{// 早饭@Overridepublic void breakfast() {System.out.println("早饭:包子");}// 午饭@Overridepublic void lunch() {System.out.println("午饭:炒面");}// 晚饭@Overridepublic void dinner() {System.out.println("晚饭:喝尿");}
    }
    
  • 测试

    public class TemplateDemo {public static void main(String[] args) {// 儿子的一日三餐Son son = new Son();System.out.println("==============儿子的一日三餐==============");son.threeMealsDaily();// 女儿的一日三餐Daughter daughter = new Daughter();System.out.println("==============女儿的一日三餐==============");daughter.threeMealsDaily();}
    }
    
  • 输出

    在这里插入图片描述

三、实践

在java中我们提倡面向接口编程,因此需要定义一个接口,来定义其实现类中的行为。另外需要将父类设置为抽象类并定义模版方法。因此在模版方法中存在这三个组件:

  • 接口类:定义模版方法
  • 抽象类:实现接口定义的模版方法,并定义抽象方法由子类实现
  • 具体实现类:继承抽象类,并实现抽象类定义的抽象方法

下面我们对上面的入门示例进行改造

  • 接口类:定义模版方法

    public interface Daily {// 日常活动void threeMealsDaily();
    }
    
  • 抽象类:实现接口定义的模版方法,并定义抽象方法由子类实现

    模版方法threeMealsDaily()设置为public是为了在任何地方都可以调用该方法

    实现细节设置为protected是为了控制其具体实现类的位置

    public abstract class Parent implements Daily {// 一日三餐的模版public void threeMealsDaily() {// 早饭breakfast();// 午饭lunch();// 晚饭dinner();}// 早饭protected abstract void breakfast();// 午饭protected abstract void lunch();// 晚饭protected abstract void dinner();
    }
    
  • 具体实现类:继承抽象类,并实现抽象类定义的抽象方法

    public class Daughter extends Parent {// 早饭@Overridepublic void breakfast() {System.out.println("早饭:包子");}// 午饭@Overridepublic void lunch() {System.out.println("午饭:炒面");}// 晚饭@Overridepublic void dinner() {System.out.println("晚饭:喝尿");}
    }public class Son extends Parent {// 早饭@Overridepublic void breakfast() {System.out.println("早饭:喝粥");}// 午饭@Overridepublic void lunch() {System.out.println("午饭:米饭");}// 晚饭@Overridepublic void dinner() {System.out.println("晚饭:吃屎");}
    }
    
  • 测试

    public class TemplateDemo {public static void main(String[] args) {// 儿子的一日三餐Daily son = new Son();System.out.println("==============儿子的一日三餐==============");son.threeMealsDaily();// 女儿的一日三餐Daily daughter = new Daughter();System.out.println("==============女儿的一日三餐==============");daughter.threeMealsDaily();}
    }
    
  • 输出

    在这里插入图片描述

四、使用场景

  • 在java集合中,LinkedHashMap与其父类HashMap以及抽象父类AbstractMap就是模版方法设计模式的体现
  • 在spring中,DispatcherServlet与其父类爷类祖爷类也是模版方法设计模式的复杂体现

五、总结

模版方法是比较简单的一种设计模式。但他还是有一些优缺点。

优点:通过模版定义方法,提高了代码的复用性的同时也提高了子类的个性化实现

缺点:当然是java单继承的缺陷了。

纸上得来终觉浅,绝知此事要躬行。

————我是万万岁,我们下期再见————