《設計模式》- 模板模式

模板模式在諸多模式中算是比較簡單的一個,即便一個新手,也能很快的上手和使用。雖然簡單,但合理的在項目中使用帶來的好處可不小。軟件設計中有個很重要的原則:DRY(Don't Repeat Yourself),重複有很多種,比如代碼重複,邏輯重複,而模板模式的最拿手的就是消除邏輯重複。

我們先看一下模板模式的定義:在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中去實現。模板方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟。只要你學習過任何一門面嚮對象語言,那麼理解上面的定義肯定不是問題。

來看看模式的UML類圖:


AbstractClass是一個抽象類,其中templateMethod是一個final方法,封裝了具體的算法實現步驟、過程,其內部調用了其它方法。abstractMethod1與abstractMethod2是抽象方法,其具體實現由具體的子類決定,這樣子類就可以在不改變算法結構的情況下,重新定義算法中的某些步驟。值得一提的是hook方法,它是一個鉤子方法,在父類中會提供一個默認的實現,子類可以有選擇的決定是否要覆蓋鉤子方法。簡單而言,鉤子讓子類有機會修改算法中的某些步驟,是否使用鉤子完全取決於業務。


我們來看一個例子。

飲料製作
飲料 牛奶 咖啡
1. 把杯子洗乾淨。
2. 把水煮沸。
3. 把飲料放入杯子。
4. 把開水倒入杯中。
5. 加調料。
6. 攪拌。
1. 把杯子洗乾淨。
2. 把水煮沸。
3. 把奶粉放入杯子。
4. 把開水倒入杯中。
5. 加糖。
6. 攪拌。
1. 把杯子洗乾淨。
2. 把水煮沸。
3. 把咖啡放入杯子。
4. 把開水倒入杯中。
5. 加糖、伴侶。
6. 攪拌。


飲料(Beverage是一個抽象類,make方法封裝了飲料的製作流程,但具體制作什麼飲料,加不加調料、加什麼調料由給子類去決定,addCondiment方法是一個鉤子,默認什麼都不做。

public abstract class Beverage {
	public final void make() {
		System.out.println("把杯子洗乾淨。");
		System.out.println("把水煮沸。");
		this.addBeverage();
		System.out.println("把水倒入杯中。");
		this.addCondiment();
		System.out.println("攪拌。");
	}
	
	protected abstract void addBeverage();
	protected void addCondiment() {
		//默認什麼調料都不加。
	}
}

牛奶(Milk是一個實現類,僅實現addBeverage方法;Coffee也是一個實現類,實現了addBeverage,並且覆蓋了addCondiment方法(不加糖咖啡太苦啦)。

public class Milk extends Beverage {

	@Override
	protected void addBeverage() {
		System.out.println("把奶粉倒入杯口。");
	}

}
public class Coffee extends Beverage {

	@Override
	protected void addBeverage() {
		System.out.println("把咖啡倒入杯口。");
	}
	
	@Override
	protected void addCondiment() {
		System.out.println("加糖和咖啡伴侶。");
	}

}

運行結果:

public static void main(String[] args) {
	Beverage milk = new Milk();
	Beverage coffee = new Coffee();

	System.out.println("做牛奶......");
	milk.make();
	System.out.println("\n做咖啡......");
	coffee.make();
}
做牛奶......
把杯子洗乾淨。
把水煮沸。
把奶粉倒入杯口。
把水倒入杯中。
攪拌。

做咖啡......
把杯子洗乾淨。
把水煮沸。
把咖啡倒入杯口。
把水倒入杯中。
加糖和咖啡伴侶。
攪拌。

JDK中有哪些使用模板模式的部分?

像Collections.sort、Arrays.sort等方法,都需要一個實現Comparator接口的對象來決定如何比較對象(實現compare方法);

又如File.listFiles方法需要一個實現FileFilter接口的對象來決定如何過濾文件(通過實現accept方法),在JDK中類似的場景還有很多,這裏就不一一例舉了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章