咖啡和茶的冲泡
假设咖啡的冲泡过程为
把水煮沸--》用沸水泡咖啡--》把咖啡倒入杯子--》加糖和奶
,而茶的冲泡过程为把水煮沸--》用沸水泡茶叶--》把茶倒入杯子--》加柠檬
。在现有实现的基础上,如何体现更好的封装性?
public class Coffee{
// 咖啡冲泡过程
void prepareRecipe(){
boilwater();
brewCoffeeGrinds();
pourInCup();
addSugarAndMilk();
}
// 上述方法的具体实现
}
public class Tea{
// 茶冲泡过程
void prepareRecipe(){
boilwater();
steepTeaBag();
pourInCup();
addLemon();
}
// 上述方法的具体实现
}
模板方法模式
- 定义了一个算法的步骤,并将一些实现步骤延迟到子类中(即让子类提供某些步骤的实现)
- 工厂方法是模板方法的特殊版本
模式 | 表述 |
---|---|
模板方法 | 子类决定如何实现算法中的某些步骤 |
策略 | 封装可交换的行为,然后使用委托决定要采用哪一个行为 |
工厂方法 | 哪个具体类 |
提取相似点
在两者制作过程中,
boilWater
方法和pourInCup
方法都是一样的,可以抽象放到基类中
public abstract class CaffeinBeverage{ // 基类
// 其余代码后续说明
void boilWater(){...}
void pourInCup(){...}
}
抽象prepareRecipe方法
除了上述两个一样的方法,还存在相似点:
brewCoffeeGrind
和steepTeaBag
以及addSugarAndMilk
和addLemon
是两对差异不大的方法,可以将第一组抽象为brew
方法,第二组抽象为addCondiments
方法,同样放到基类中
public abstract class CaffeinBeverage{
// 声明为final是因为不希望子类去重写该方法
final void prepareRecipe(){
boilWater();
brew();
pourInCup();
addCondiments();
}
// 声明为抽象,让子类去实现
abstract void brew();
abstract void addCondiments();
void boilWater(){...}
void pourInCup(){...}
}
开始冲泡
以冲泡茶为例
public class Tea extends CaffeinBeverage{
public void brew(){
System.out.println("Steeping the tea");
}
public void addCondiments(){
System.out.println("Adding Lemon");
}
}
对模板方法进行挂钩
- 钩子是一种被声明在抽象类中的方法,它具有空或默认实现
- 钩子是为了让子类有能力对算法的不同点进行挂钩(由子类决定要不要挂钩)
public abstract class CaffeinBeverageWithHook{
final void prepareRecipe(){
boilWater();
brew();
pourInCup();
if(customerWantsCondiments){
addCondiments();
}
}
// 钩子,子类可以选择覆盖
boolean customerWantsCondiments(){
return true;
}
// 其余代码一致
}
排序鸭子
模板方法排序
在
Java Arrays
类中提供了模板方法进行排序,其中Sort
是模板方法,并且**CompareTo
延迟到子类去实现**
// 之所以定义为static是因为数组无法继承,也就无法通过xxx.sort使用排序,而是Arrays.sort(xxx)
public static void sort(Object[] a){
Object[] aux = (Object[])a.clone();
merge(aux, a, 0, a.length, 0);
}
private static void merge(Object[] src, Object[] dest, int low, int high, int off){
for(int j = i; j > low && ((Comparable)dest[j - 1]).compareTo((Comparable)dest[j]) > 0; j--){
swap(dest, j, j-1); // 在Arrays类中定义了
}
return;
}
鸭子类
public class Duck implements Comparable{ // 实现Comparable接口中的compareTo方法,
int weight;
public int compareTo(Object o){
Duck otherDuck = (Duck)o;
if(this.weight < otherDuck.weight){
return -1;
}else if(this.weight == otherDuck.weight){
return 0;
}else{
return 1;
}
}
}