Head First设计模式(阅读笔记)-09.模板方法模式

咖啡和茶的冲泡

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


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方法

除了上述两个一样的方法,还存在相似点:brewCoffeeGrindsteepTeaBag以及addSugarAndMilkaddLemon是两对差异不大的方法,可以将第一组抽象为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 设计模式-模板方法模式

设计模式-模板模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值