设计模式之模版方法
往期文章
- 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单继承的缺陷了。
纸上得来终觉浅,绝知此事要躬行。
————我是万万岁,我们下期再见————