? 模板方法模式就是在某个方法中定义了一个算法的骨架,将某些步骤延迟到子类中实现。以此来让子类在不改变算法的结构的情况下重新定制算法的某些行为 / 步骤。
? 在我们进行的烹饪的过程中,有些菜肴的制造步骤是固定的,比如炒菜之前要先热锅冷油、加入姜蒜葱爆香,然后加入要炒的备菜,最后放入调料调味进行翻炒,然后出锅。不同的菜肴可能只需要在某些步骤上有所差异,比如加入的调料不同,要炒的备菜不同。这种情况下,就可以使用模板方法模式,先定义一个基本的烹饪流程(模板方法),然后让不同的菜肴根据需求实现不同的细节(抽象方法)。
package com.technologystatck.designpattern.mode.template;
public class Templates {
public static void main(String[] args) {
AbstractClass concreteTemplate = new ConcreteClass();
//触发整个算法的执行
concreteTemplate.templateMethod();
}
}
//定义模板类,包含模板方法,定义了算法的骨架,
//一般都加上final关键字,避免子类重写
//模板类
abstract class AbstractClass{
//模板方法,定义了算法的骨架
public final void templateMethod(){
step1();
step2();
step3();
}
//抽象方法,由子类实现
protected abstract void step1();
protected abstract void step2();
protected abstract void step3();
}
//定义具体类,实现模板类中的抽象方法
//具体类
class ConcreteClass extends AbstractClass{
@Override
protected void step1() {
System.out.println("Step 1");
}
@Override
protected void step2() {
System.out.println("Step 2");
}
@Override
protected void step3() {
System.out.println("Step 3");
}
}
小明喜欢品尝不同类型的咖啡,她发现每种咖啡的制作过程有一些相同的步骤,他决定设计一个简单的咖啡制作系统,使用模板方法模式定义咖啡的制作过程。系统支持两种咖啡类型:美式咖啡(American Coffee)和拿铁(Latte)。
咖啡制作过程包括以下步骤:
其中,美式咖啡和拿铁的调料添加方式略有不同, 拿铁在添加调料时需要添加牛奶Adding milk
多行输入,每行包含一个数字,表示咖啡的选择(1 表示美式咖啡,2 表示拿铁)。
根据每行输入,输出制作咖啡的过程,包括咖啡类型和各个制作步骤,末尾有一个空行。
package com.technologystatck.designpattern.mode.template;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
int coffeeType = scanner.nextInt();
CoffeeMarkerTemplate coffeeMarkerTemplate = null;
if(coffeeType == 1){
coffeeMarkerTemplate = new AmericanoCoffeeMarker();
} else if (coffeeType == 2) {
coffeeMarkerTemplate = new LatteCoffeeMarker();
}else {
System.out.println("Invalid coffee type");
continue;
}
//制作咖啡
coffeeMarkerTemplate.makeCoffee();
}
}
}
//抽象类
abstract class CoffeeMarkerTemplate{
//添加咖啡名称字段
private String coffeeName;
//构造函数,接受咖啡名称参数
public CoffeeMarkerTemplate(String coffeeName){
this.coffeeName=coffeeName;
}
//模板方法定义咖啡制作过程
final void makeCoffee(){
System.out.println("Making "+coffeeName+":");
grindCoffeeBeans();
brewCoffee();
addCondiments();
System.out.println();
}
//具体步骤的具体实现由子类提供
abstract void grindCoffeeBeans();
abstract void brewCoffee();
//添加调料的默认实现
void addCondiments(){
System.out.println("Adding condiments");
}
}
//具体的美式咖啡类
class AmericanoCoffeeMarker extends CoffeeMarkerTemplate{
//构造函数传递咖啡名称,这里使用了父类的构造函数,
public AmericanoCoffeeMarker() {
super("American Coffee");
}
@Override
void grindCoffeeBeans() {
System.out.println("Grinding coffee beans");
}
@Override
void brewCoffee() {
System.out.println("Brewing coffee");
}
}
//具体的拿铁咖啡类
class LatteCoffeeMarker extends CoffeeMarkerTemplate{
//构造函数传递咖啡名称,这里使用了父类的构造函数,
//并传递了咖啡名称参数
public LatteCoffeeMarker() {
super("Latte");
}
//构造函数传递咖啡名称
@Override
void grindCoffeeBeans() {
System.out.println("Grinding coffee beans");
}
@Override
void brewCoffee() {
System.out.println("Brewing coffee");
}
//添加调料的特定实现
void addCondiments(){
System.out.println("Adding milk");
System.out.println("Adding condiments");
}
}