序言
模板方法模式通过把不变的行为搬移到父类(抽象类),去除了子类中的重复代码;对于不同的子类有不同实现的行为,在父类中声明一些抽象方法来迫使子类实现剩余的逻辑,提高程序的扩展性。
模板方法有如下几种角色:
-
抽象模板角色:抽象类,该类包含以下几类方法:
1. 模板方法:final类型的具体方法,给出了实现业务操作的顶级逻辑,内部调用了由子类实现的抽象方法。
2. 抽象方法:实现顶级逻辑的基本操作,由子类实现。
3. 钩子方法:具体方法,方法体为空,可被子类置换。
4. 具体方法:private类型的具体方法,作为实现顶级逻辑的一部分基本操作。 -
具体模板角色:具体类
模板方法模式
模板方法模式的结构如下图:
套路:
- 梳理原类中方法的业务逻辑,抽象出顶级逻辑,形成抽象模板类,模板方法,抽象方法
- 根据职责划分,创建相关子类,形成具体模板类,形成具体操作方法
/**
* 抽象模板角色-打印机
*/
public abstract class Printer {
//模板方法
public final double getAmount(int num){
String printType = getPrinterType();
double paperPrice = getPaperPrice(printType);
return num * paperPrice;
}
//钩子方法
public String getPrinterName(){return null;}
//抽象方法
protected abstract String getPrinterType();
//抽象方法
protected abstract double getPaperPrice(String printerType);
//具体方法
private void print(){
//打印相关业务
}
}
/**
* 具体模板角色-石墨打印机
*/
public class GraphitePrinter extends Printer{
@Override
protected String getPrinterType() {
return "石墨打印";
}
@Override
protected double getPaperPrice(String printerType) {
if("石墨打印".equals(printerType)){
return 1;
}else{
throw new RuntimeException("没有" + printerType + "这种类型");
}
}
}
/**
* 具体模板角色-激光打印机
*/
public class LaserPrinter extends Printer{
@Override
protected String getPrinterType() {
return "激光打印";
}
@Override
protected double getPaperPrice(String printerType) {
if("激光打印".equals(printerType)){
return 2;
}else{
throw new RuntimeException("没有" + printerType + "这种类型");
}
}
}
/**
* 测试模板方法模式.
*/
public class TemplateMethodTest {
@Test
public void testTemplateMethod(){
//1.激光打印3张纸
new LaserPrinter().getAmount(3);
//2.石墨打印3张纸
new GraphitePrinter().getAmount(3);
}
}
吹牛:
- 模板方法模式展现继承复用的可用之地,以往都是采用委派关系来代继承关系
- 当方法包含了太多的代码时,不妨试着抽取几个类,几个方法,利用模板方法模式重构一下
后记
- 撰写本文考了不少博文,在此一并谢过。
《JAVA与模式》之模板方法模式- 转载时,请注明出处,这是人格的一种体现。
https://www.zybuluo.com/BertLee/note/853031- 能力有限,如有纰漏,请在评论区指出,老朽虽一把年纪,必当感激涕零,泪如雨下。