Head First 設計模式之模版方法模式(Java例子)

前言:

來源於《head first 設計模式》。當作讀書筆記了,這次看的是第8章模版方法模式。難頂呀每晚看完書,第二天早上總結。理解到了以前學習java、spring中的一些基礎的概念,蠻有用的,希望自己可以一直堅持下去吧。

模版方法模式的概念

在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模版方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟

適配器模式的uml圖

在這裏插入圖片描述

  • AbstractClass:在templateMethod中定義了算法的骨架,具體的實現方法operation1、2交給子類來實現
  • ConcreteClass:實現operation1、2算法。
    例子:
  • 咖啡沖泡法:
    1.把水煮沸
    2.用沸水沖泡咖啡
    3.把咖啡倒進杯子
    4.加糖和牛奶
  • 茶沖泡法
    1.把水煮沸
    2.用沸水沖泡茶葉
    3.把茶倒進杯子
    4.加檸檬

茶和咖啡的基類—AbstractClass

public abstract class CaffeineBeverage {
    // 現在,用同一個prepareRecipe()方法來處理茶和咖啡。
    // prepareRecipe()方法被聲明爲final,因爲我們不希望子類覆蓋這個方法
    // 我們將第2步和第4步泛化成爲brew()和addCondiments()
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    // 因爲咖啡和茶處理這些方法的做法不同,所以這兩個方法必須被聲明爲抽象,
    // 剩餘的東西留給子類去操心
    abstract void addCondiments();
    abstract void brew();

    public void boilWater() {
        System.out.println("Boiling water");
    }

    public void pourInCup() {
        System.out.println("Pouring into cup");
    }
}

coffee和茶的實現類

實現對應的算法骨架中,自己改變的那部分方法。

public class Coffee extends CaffeineBeverage {
    @Override
    void brew() {
        System.out.println("Dripping coffee through filter");
    }

    @Override
    void addCondiments() {
        System.out.println("Adding Sugar and Milk");
    }
}

public class Tea extends CaffeineBeverage {
    @Override
    void brew() {
        System.out.println("Steeping the tea");
    }

    @Override
    void addCondiments() {
        System.out.println("Adding Lemon");
    }
}

hook鉤子方法的使用

public abstract class CaffeineBeverageWithHook {
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        // 我們加上了一個小小的條件語句,而該條件是否成立,
        // 是由一個具體方法customerWantsCondiments()決定的。
        // 如果顧客“想要”調料,只有這時我們才調用addCondiments()。
        if (customerWantsCondiments()) {
            addCondiments();
        }
    }

    abstract void addCondiments();
    abstract void brew();

    public void boilWater() {
        System.out.println("Boiling water");
    }

    public void pourInCup() {
        System.out.println("Pouring into cup");
    }

    // 我們在這裏定義了一個方法,(通常)是空的缺省實現。這個方法只會返回true,不做別的事。
    // 這就是一個鉤子,子類可以覆蓋這個方法,子類通過覆蓋這個鉤子來提供自己對於某部分算法的取捨。
    boolean customerWantsCondiments() {
        return true;
    }
}

hook方法子類實現

public class TeaWithHook extends CaffeineBeverageWithHook {
 
	public void brew() {
		System.out.println("Steeping the tea");
	}
 
	public void addCondiments() {
		System.out.println("Adding Lemon");
	}
 
	public boolean customerWantsCondiments() {

		String answer = getUserInput();

		if (answer.toLowerCase().startsWith("y")) {
			return true;
		} else {
			return false;
		}
	}
 
	private String getUserInput() {
		// get the user's response
		String answer = null;

		System.out.print("Would you like lemon with your tea (y/n)? ");

		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		try {
			answer = in.readLine();
		} catch (IOException ioe) {
			System.err.println("IO error trying to read your answer");
		}
		if (answer == null) {
			return "no";
		}
		return answer;
	}
}

測試代碼

public class BeverageTestDrive {
	public static void main(String[] args) {
 
		Tea tea = new Tea();
		Coffee coffee = new Coffee();
 
		System.out.println("\nMaking tea...");
		tea.prepareRecipe();
 
		System.out.println("\nMaking coffee...");
		coffee.prepareRecipe();

 
		TeaWithHook teaHook = new TeaWithHook();
 
		System.out.println("\nMaking tea...");
		teaHook.prepareRecipe();
	}
}

總結

Java中也有模板方法的體現。那就是對數組進行排序的時候實現Comparable接口,提供這個接口所聲明的compareTo()方法。
策略模式與模版模式的不同:
則略模式:針對整個算法的實現,用所組合的類實現了整個算法,委託的方式實現。
模版模式:針對算法中的每個步驟,採用繼承的形式來實現,讓子類來重寫需要修改的算法步驟。

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