【设计模式与体系结构】行为型模式-模板方法模式
简介
模板方法模式(Template Method Pattern)是一种行为型模式,其核心是在父类中定义好算法的流程,将流程中通用的部分直接在父类中实现,同时将一些特定的部分延迟到子类中实现。
模板方法模式的角色
- 抽象类:定义模板方法(通常定义为 final 方法,防止子类篡改流程)和基本操作的具体方法、抽象方法及钩子方法(钩子方法用于控制部分方法是否执行)
- 具体子类:继承自抽象类,并实现抽象类的抽象方法
模板方法模式的优点
- 抽象类集中控制流程,统一管理,代码复用性强,减少重复的代码
- 符合开闭原则,扩展子类时不需要修改已有代码
- 钩子方法提供了更灵活的扩展点
模板方法模式的缺点
- 当修改父类时,维护子类的成本可能会骤增
- 抽象类与子类之间是继承关系,类之间的耦合性稍大
模板方法模式的使用场景
通用流程固定、细节可定制的业务场景:如入职的固定流程(打印简历->复印证件->签订合同)、冲泡饮料(烧水->倒入饮料->倒入开水->品尝)以及做菜(洗菜->炒菜->装盘)等,这些场景整体执行顺序是固定的,仅部分细节可由子类自定义实现
代码开发与框架设计场景:多个子类具有相似的算法流程,仅个别步骤实现不同。框架定义好流程,将业务相关的可变步骤交给框架使用者提供继承子类来实现,例如 Spring 框架中的 JdbcTemplate。
正文
以做菜(洗菜->炒菜->装盘)为案例,进行代码分析。
首先定义一个抽象类 Cook.java,做菜的洗菜和装盘流程是通用的,而炒菜的具体方案是因菜而异的,因此将炒菜的方法延迟到子类实现。由于部分食材从菜市场买回来是可以直接进行烹饪而不需要经过清洗的,因此再提供一个钩子方法 hook() 用于控制是否执行洗菜方法。具体代码如下:
public abstract class Cook {
public final void getFood() {// 通用流程
if (!hook()) {
wash();
}
cook();
place();
}
/*洗菜*/
public void wash() {
System.out.println("用水洗菜");
}
/*炒菜的方式有很多种,可以蒸、煮、拌或炒等*/
public abstract void cook();
/*摆盘*/
public void place() {
System.out.println("把菜装进盘子里");
}
/**
* 钩子方法
* 比方说,钩子方法控制的是洗菜方法 wash(),若用钩子方法改变该流程
* @return 默认返回 false,代表默认执行 wash();若返回 true,代表不执行 wash()
*/
public boolean hook() {
return false;
}
}
定义一个煮青菜类 CookingVegetables.java:
public class CookingVegetables extends Cook {
@Override
public void cook() {
System.out.println("炒青菜");
}
}
定义一个煮鸡肉类 CookingChicken.java:
public class CookingChicken extends Cook {
@Override
public void cook() {
System.out.println("煮鸡肉");
}
@Override
public boolean hook() {
System.out.println("新鲜鸡肉不用洗");
return true;
}
}
定义一个客户端:
public class Client {
public static void main(String[] args) {
Cook cookingChicken = new CookingChicken();
cookingChicken.getFood();
Cook cookingVegetables = new CookingVegetables();
cookingVegetables.getFood();
}
}
执行的结果为:

浙公网安备 33010602011771号