模板方法模式
简介:
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法的情况下,重新定义算法中的某些步骤。
要想明白模板方法模式首先我们将它分解为几个部分:
1. 抽象模板(抽象类):
- 抽象方法,子类必须要实现的业务方法
- 具体方法(final),必须不被重写的方法
- 钩子方法,子类可重写,可不重写的方法
- 模板方法b,按照一定的顺序引用的抽象方法、具体方法、钩子方法
2.具体模板(extends 抽象类):
- 必须重写抽象模板中的抽象方法,根据自身特点实现具体的逻辑内容
- 选择性的重写钩子方法
- 其他自身的方法
3.测试:
- 得到某个具体模板的对象a
- 对象a调用模板方法b获取模板。如:a.b
实例:
Head First 中模板方法中的举例:饮料店中生产饮料的过程方法
Table | coffer | tea |
---|---|---|
步骤一 | 把水煮沸 | 把水煮沸 |
步骤二 | 用沸水冲咖啡 | 用沸水泡茶 |
步骤三 | 倒入杯子中 | 倒入杯子中 |
步骤四 | 加入牛奶 | 加入蜂蜜 |
抽象模板类
我们将这四个步骤分别看做一种方法。由于步骤一和步骤三相同,我们将它设置为final方法,步骤二和步骤四有差异,我们只能定义抽象方法,由具体的子类实现相应的步骤.
- 步骤一:public final toBoilWater(){};
- 步骤二:abstract void make();
- 步骤三:public final pourToCup(){};
- 步骤四:abstract void add();
- 步骤五:void hook(){};// 一个可重写,不可重写的钩子方法
通过上面我们发现两种饮料生产过程几乎相同,我们将这个步骤顺序当做制作所有饮料的一个规范,将它封装到一个方法中,于是就有了模板方法。
public final void getDrink(){
toBoilWater();
make();
pourToCup();
add();
}
至此抽象模板实现完毕
具体模板类
- 咖啡的制作:
public class coffee extends cc {
@Override
void make() {
System.out.println("倒入咖啡");
}
@Override
void Add() {
System.out.println("加入牛奶");
}
}
2.茶的制作:
public class tea extends cc {
@Override
void make() {
System.out.println("我在泡茶");
}
@Override
void Add() {
System.out.println("我往里面加入了蜂蜜");
}
}
实现:
public class text {
public static void main(String[] arg) {
coffee co=new coffee();
co.getDrink();
tea te=new tea();
te.getDrink();
}
}
至此,一个模板方法模式算是实现了,但是我们 还没有使用过钩子方法
钩子方法:一个在抽象模板类中的具体方法,它可由适当的场合由子类重写或者不用重写。
比如:我们要在制作咖啡饮料的时候,加入一个由用户选择的情况,用于只有在输入”y”时才可以继续制作咖啡。这里我们就需要使用钩子方法,由子类重写钩子方法,然后在调用子类中自身特有的方法来进行判定。
抽象模板类:
public abstract class cc {
public final void getDrink(){
toBoilWater();
make();
pourToCup();
hook(); // 钩子方法
Add();
}
abstract void make();
abstract void Add();
private void toBoilWater() {
System.out.println("我在煮开水");
}
private void pourToCup() {
System.out.println("我在往杯子里面倒");
}
public boolean hook(){ // 钩子方法,在子类实现具体的操作
return true;
}
}
具体模板类:咖啡
public class coffee extends cc {
@Override
void make() {
System.out.println("倒入咖啡");
}
@Override
void Add() {
System.out.println("加入牛奶");
}
@Override
public boolean hook() { // 重写钩子方法
String input=getInput(); // 钩子方法调用coffer类中的具体方法
if (input.toLowerCase()=="y") { // 获取输入字符串的首字母
return true;
}else {
return false;
}
}
private String getInput() {
String inputString=null;
System.out.println("请输入是否要加入牛奶:yes or no");
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
try {
inputString=in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
if(inputString==null){
return "no";
}
return inputString;
}
}
以上根据Head First 的理解下作的笔记,记忆力不好,刚接触编程,理解的很浅显,只当自己的自学笔记。