一、模板方法模式
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
二、设计原则
别调用我们,我们会调用你,高层组件控制低层组件。
三、实例
咖啡冲泡法 茶冲泡方法
1、把水煮沸 1、把水煮沸
2、用煮沸的水冲泡咖啡 2、把煮沸的水浸泡茶叶
3、把咖啡倒进杯子 3、把茶倒进杯子
4、加糖和牛奶 4、加柠檬
四、代码实现
1、原生类
package com.oyhp.protogenesis;
//原生咖啡类
public class Coffee {
/*
* 每个步骤方法都被实现在分离的方法中,煮沸水,冲泡咖啡,把咖啡倒进杯子里,加糖加奶四个算法
*/
public void prepareRecipe(){
this.boilWather();
this.brewCoffeeGrinds();
this.pourInCup();
this.addSugarAndMilk();
}
public void boilWather(){
System.out.println("Boiling water");
}
public void brewCoffeeGrinds(){
System.out.println("Dripping Coffee through filter");
}
public void pourInCup(){
System.out.println("Pouring into cup");
}
public void addSugarAndMilk(){
System.out.println("Adding Sugar and Milk");
}
}
package com.oyhp.protogenesis;
//原生茶类
public class Tea {
/*
* 每个步骤方法都被实现在分离的方法中,煮沸水,冲泡茶叶,把茶倒进杯子里,加柠檬四个算法
*/
public void prepareRecipe(){
this.boilWather();
this.steepTeaBag();
this.pourInCup();
this.addLemon();
}
public void boilWather(){
System.out.println("Boiling water");
}
public void steepTeaBag(){
System.out.println("Dripping Coffee through filter");
}
public void pourInCup(){
System.out.println("Pouring into cup");
}
public void addLemon(){
System.out.println("Adding Sugar and Milk");
}
}
2、模板方法模式
package com.oyhp.packaging;
//抽象饮料类
public abstract class Beverage {
/*
* prepareRecipe()是我们的模板方法
* 因为:
* 1、毕竟它是一个方法
* 2、它用作一个算法模板,在这个例子中,算法是用来制作咖啡和饮料的
*/
public final void prepareRecipe(){
this.boilWater();
this.brew();
this.pourInCup();
//这就是钩子的作用
if(this.customerWantsCondiments()){
this.addCondiments();
}
}
/*
* 咖啡和茶同样都是下面四步
* 1、把水煮沸
* 2、冲泡
* 3、把饮料倒进杯子
* 4、加调料
*/
abstract void brew();
abstract void addCondiments();
void boilWater(){
System.out.println("Boiled Water");
}
void pourInCup(){
System.out.println("Pouring into cup");
}
//钩子-可以有"默认不做任何事的方法",子类视情况要不要覆盖钩子
boolean customerWantsCondiments(){
return true;
}
}
package com.oyhp.packaging;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Coffee extends Beverage{
//覆盖了父类的钩子,提供了自己的服务
@Override
boolean customerWantsCondiments() {
// TODO Auto-generated method stub
String answer = this.getUserInput();
if(answer.toLowerCase().startsWith("y")){
return true;
}else{
return false;
}
}
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("Dripping Coffee through filter");
}
@Override
void addCondiments() {
// TODO Auto-generated method stub
System.out.println("Adding Sugar and Milk");
}
//询问顾客是否要加糖
private String getUserInput(){
String answer = null;
System.out.println("Would you like milk and sugar with your coffee(y/n)?");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
answer = in.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(answer == null){
return "no";
}
return answer;
}
}
package com.oyhp.packaging;
public class Tea extends Beverage{
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("Dripping Coffee through filter");
}
@Override
void addCondiments() {
// TODO Auto-generated method stub
System.out.println("Adding Sugar and Milk");
}
}
3、测试类
package com.oyhp.test;
import com.oyhp.packaging.Beverage;
import com.oyhp.packaging.Coffee;
import com.oyhp.packaging.Tea;
public class DoRun {
public static void main(String[] args) {
Beverage coffee = new Coffee(); //一杯咖啡
Beverage tea = new Tea(); //一杯茶
//然后各自调用模板方法
coffee.prepareRecipe();
System.out.println("\n");
tea.prepareRecipe();
}
}
五、类图
六、总结
模板方法定义了一个算法步骤,并允许子类为一个或多个步骤提供实现。