假设咖啡的冲泡过程为
把水煮沸--》用沸水泡咖啡--》把咖啡倒入杯子--》加糖和奶,而茶的冲泡过程为把水煮沸--》用沸水泡茶叶--》把茶倒入杯子--》加柠檬。在现有实现的基础上,如何体现更好的封装性?
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;
}
}
}