模板方法模式将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。这可以确保算法的结构保持不变,同时由子类提供部分实现。
模板方法模式
定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
UML图
例子
我们知道泡茶和泡咖啡步骤大致一致,分别是1 把水煮沸 2 用沸水煮泡咖啡/浸泡茶叶 3 把咖啡/茶倒进杯子 4 加适当调料
可以看到,泡茶和泡咖啡的第一步和第三步是一样的,只有在第二步和第四步才会出现差异,如果我们按照冲泡的方法一个个写的话,代码会有重复,且不好维护,使用模板方法的话,可以很好的解决这一问题。
先写抽象模板
package template;
/**
* 模板方法,定义了具体的步骤,但是详细的实现交由子类来完成
*/
public abstract class Beverage {
final void prepareRecipe(){
boilWater();
brew(); //交由子类实现
pourInCup();
addCondiments(); //;交由子类实现
}
abstract void brew();
abstract void addCondiments();
void boilWater(){
System.out.println("Boiling water");
}
void pourInCup(){
System.out.println("Pouring into cup");
}
}
让茶/咖啡来具体实现煮和添加调料的方法:
茶 添加茶 添加柠檬
package template;
/**
* 茶
* 添加茶
* 添加柠檬
*/
public class Tea extends Beverage {
@Override
void brew() {
System.out.println("add Tea");
}
@Override
void addCondiments() {
System.out.println("add lemon");
}
}
咖啡 添加咖啡 添加牛奶和糖
package template;
/**
* 咖啡
* 添加咖啡
* 添加牛奶和糖
*/
public class Coffee extends Beverage {
@Override
void brew() {
System.out.println("drip coffee through filter");
}
@Override
void addCondiments() {
System.out.println("add milk and sugar");
}
}
测试
package test.template;
import template.Beverage;
import template.Coffee;
import template.Tea;
public class test {
public static void main(String args[]){
Beverage tea = new Tea();
tea.prepareRecipe();
Beverage coffee = new Coffee();
coffee.prepareRecipe();
}
}
小结
模板方法帮助我们实现了代码的复用,也提高了拓展性,但是因为引入了抽象类和其不同的实现类,导致代码膨胀的很快,其实这也是Java饱受诟病的一点。
源码在这里:我的github地址
其他设计模式:设计模式学习笔记