定义
模板方法模式在一个方法中定义一个算法的骨架, 而将一些步骤延迟到子类中, 模板方法使得子类可以在不改变算法结构的情况下, 重新定义算法中的某些步骤
- 模板方法定义了一个算法的步骤, 并允许子类为一个或多个步骤提供实现
- java的数组的排序就使用了模板方法模式, 需要排序的对象需要实现Comparable接口或是重写方法
- java的io的InputStream类的read()方法, 是由子类实现, 而这个方法又会被read(byte b[], int off, int len)模板方法使用
- 策略模式组合的类实现了整个算法, 而模板方法允许子类补充实现
- 模板方法的抽象类可以定义具体方法, 抽象方法, 和钩子, 钩子是一种方法, 它在抽象类中不做事, 或者只做默认的事情, 子类可以选择要不要去覆盖它
模板方法模式与策略模式的比较
1.策略模式定义一个算法家族, 并让这些算法可以互换, 因为每一个算法都被封装起来了, 所以客户可以轻易的使用不同的算法
2.模板方法模式定义了一个算法的大纲, 由子类定义其中某些步骤的内容, 这样算法中的不同步骤可以有不同的实现细节, 但算法的结构依然维持不变
3.策略模式使用的是对象组合, 模板方法使用的是继承抽象类
设计原则:
- 好莱坞原则: 别调用(打电话)我们, 我们会调用(打电话)你
在好莱坞原则之下, 我们允许低层组件将自己挂钩到系统上, 但是高层组件会决定什么时候和怎样使用这些低层组件
案例
背景:设计类来描述茶和咖啡冲调的步骤, 并抽取共同的代码
茶冲调的步骤:1.煮开水;2.冲泡茶;3.倒入杯中;4.加柠檬
咖啡冲调的步骤:1.煮开水;2.冲泡咖啡;3.倒入杯中;4.加糖和牛奶
基类, 设计prepareRecipe模板方法, 并声明为final不让子类重写;
相同的部分在基类中实现, 不同的部分声明为抽象方法, 由子类实现
public abstract class CaffeineBeverage {
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
private void boilWater() {
System.out.println("煮开水");
}
abstract void brew();
private void pourInCup() {
System.out.println("倒入杯中");
}
abstract void addCondiments();
}
茶
public class Tea extends CaffeineBeverage {
@Override
void brew() {
System.out.println("冲泡茶");
}
@Override
void addCondiments() {
System.out.println("加柠檬");
}
}
咖啡
public class Coffee extends CaffeineBeverage {
@Override
void brew() {
System.out.println("冲泡咖啡");
}
@Override
void addCondiments() {
System.out.println("加糖和牛奶");
}
}
设计原则分析: