假设咖啡的冲泡过程为
把水煮沸--》用沸水泡咖啡--》把咖啡倒入杯子--》加糖和奶
,而茶的冲泡过程为把水煮沸--》用沸水泡茶叶--》把茶倒入杯子--》加柠檬
。在现有实现的基础上,如何体现更好的封装性?
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(){...}
}
除了上述两个一样的方法,还存在相似点:
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;}}
}
Head First 设计模式-模板方法模式
设计模式-模板模式