在模板方法模式中有一个抽象的类,该抽象类定义了相关方法的模板,它的子类可以根据需要重写模板中的方法,但调用还是会以在抽象类中定义好的方式进行。
概述
实现一些操作时,整体步骤很固定,但是呢。就是其中一小部分需要改变,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
优点:
- 不变的部分已封装好,剩余可变的部分可随意扩展。
- 行为延迟到子类实现,但控制权在父类手中。
- 提取出了公共代码,维护变得简单。
缺点:
- 每个不同的实现都需要一个子类,会导致类的个数增加,使得系统更加庞大。
- 通过继承的方式实现,而不是组合。
使用场景:
- 多个子类共有一些方法,且逻辑相同时。
- 代码逻辑重要且复杂,可以将核心方法抽象出来设计为模板,且其它相关的方法可延迟到子类中实现时。
- 重构时模板方法模式也是一种常见的处理手段,可以把相同的代码抽取到父类中,然后通过钩子函数约束其行为。
如果想防止不规范操作,可在模板方法前面加上
final关键字。
示例
去餐厅吃饭,餐厅给我们提供了一个模板就是:看菜单,点菜,吃饭,付款,走人 (这里 “点菜和付款” 是不确定的由子类来完成的,其他的则是一个模板。)
先定义一个模板。把模板中的点菜和付款,让子类来实现。
//模板方法public abstract class RestaurantTemplate {// 1.看菜单public void menu() {System.out.println("看菜单");}// 2.点菜业务abstract void spotMenu();// 3.吃饭业务public void havingDinner(){ System.out.println("吃饭"); }// 3.付款业务abstract void payment();// 3.走人public void GoR() { System.out.println("走人"); }//模板通用结构public void process(){menu();spotMenu();havingDinner();payment();GoR();}}
具体的模板方法子类1
public class RestaurantGinsengImpl extends RestaurantTemplate {void spotMenu() {System.out.println("人参");}void payment() {System.out.println("5快");}}
具体的模板方法子类2
public class RestaurantLobsterImpl extends RestaurantTemplate {void spotMenu() {System.out.println("龙虾");}void payment() {System.out.println("50块");}}
客户端测试
public class Client {public static void main(String[] args) {//调用第一个模板实例RestaurantTemplate restaurantTemplate = new RestaurantGinsengImpl();restaurantTemplate.process();}}
总结
模板方法实际上可以理解成一个封装好了的固定流程,第一步该做什么,第二步该做什么其实都已经在抽象类中定义好了。子类可以有不同的算法实现,可以在框架不被修改的情况下实现某些步骤的算法替换。
