2009年8月12日 星期三

Design Pattern - Template Pattern

Template Pattern

通常, 共用的方法, 我們可能會在父類別先實作, 不同的部份再定義成抽象, 由子類去實作

而Template Pattern只是告訴我們, 這些由子類別去實作的方法, 若也能抽象化呢?

舉個例子:
coco飲料店要做一杯飲料, 其中addWater(), putCup()是共用的
prepareRecipt()可以定成抽象, 各個飲料不同之處去實作


public abstract class CocoBeverage{

//boilWater(), pourlnCup(), 是共用的方法
public void addWater(){
//實作
}
public void putCup(){
//實作
}
public abstract void prepareRecipt();
}

public class MilkTea extends CocoBeverage{

public void prepareRecipt(){
addMilk();
}
public void addMilk(){
...
}
}

public class LemonTea extends CocoBeverage{

//略
public void addLemon(){
...
}
}


Template Pattern 說明, 可以提供一個公開方法, 定義出執行的步驟, 而怎麼實作可交由子類負責

所以, 上面的addMilk(), addLemon(), 其實很相同, 若能以 addCondiment統一命名, 來把這步驟抽象化呢?


public abstract class CocoBeverage{

public void addWater(){
...
}
public void putCup(){
...
}
final void executeBeverage(){ //final 注意, 不希望被繼承

addWater();
addCondiment();
putCup();
}

public abstract void addCondiment();
}

public class MilkTea extends CocoBeverage{

public void addCondiment(){
//實作加入milk
}
}

public class LemonTea extends CocoBeverage{

public void addCondiment(){
//實作加入lemon
}
}


所以我們只要去使用CocoBeverage 提供的 executeBeverage, 就可做飲料
提供抽象的CocoBeverage類別, 就是要減少client在使用時, 只依賴這class, 而不要與未來會實作的class有關聯(可以一直增加飲料種類)

--

補充1:
我們是不是可以在 executeBeverage(), 提供的template methed命名上, 加上Impl呢?
executeBeverageImpl()或templateExecuteBeverage()呢? 如此更可以讓別人一看就知用途


補充2:
Design Pattern 一書中, 提到一種勾子的模式, hook()

若我們在抽象CocoBeverage的template method中, 加入一個只宣告, 但不做事的空方法呢?

若有這hook()的存在, 可以讓子類別對template的步驟中, 不同點進行掛勾, 讓這些步驟有可能進行修改, 當然要不要勾, 由子類決定

同上, 做點修改

public abstract class CocoBeverage{
...略
final void executeBeverage(){

addWater();
if(hook()){ //預設一定會加調味料
addCondiment();
}
putCup();
}

public abstract void addCondiment();

public boolean hook(){ 這就是一個勾子, 子類別可以override, 以控制這template的步驟
return true;
}
}


我覺 hook()只是一種講法, 實現的情況會很多種, 所以還是要認清, pattern不是死的, 只是為了學習更好的寫法


補充3:
實作時, 要去繼承abstract的class這種方式, 彈性不夠
書上有舉例, 平時要排序時, 要去implements Comparable介面的compareTo(), 也是一種template pattern的實作
當要排序時, Collection.sort(Object o); 可以把這sort()想成template, 反正我們不用管sort()怎麼做的,
而且sort就是有固定的步驟, 且實現可由子類別控制,
只要我們把要排的object丟進去就好, Comparable介面就是讓我們控制的一個hook()

0 意見: