對於模板方法模式,我想說的是,每個寫過代碼的人都應該或多或少的用過,它的定義為:定義一個操作中的算法的框架,而將一些步驟延遲到子類中。使得子類可以不改變一個算法的結構即可重新定義該算法的某些特定步驟。說的通俗一點,就是為子類設計一個模板以便於子類復用里面的方法。為了避免子類惡意修改方法的實現細節,一般模板方法模式都會在方法上加final。
來一個簡單的例子吧,小明離職自己創業開了個蛋糕店,蛋糕店不能只賣一種蛋糕呀,於是小明決定先賣奶油蛋糕,芝士蛋糕和慕斯蛋糕。三種蛋糕如果分別做那也太麻煩了,起碼造型,烘焙和塗抹蛋糕上的東西都差不多是一樣的。所以可以定義一個抽象蛋糕模型
public abstract class AbstractCake{ protected abstract void shape(); protected abstract void apply(); protected abstract void brake(); }
下面就可以批量生產三種蛋糕咯
class CreamCake extends AbstractCake { @Override protected void shape() { System.out.println("奶油蛋糕造型"); } @Override protected void apply() { System.out.println("奶油蛋糕塗抹"); } @Override protected void brake() { System.out.println("奶油蛋糕烘焙"); } } class CheeseCake extends AbstractCake { @Override protected void shape() { System.out.println("芝士蛋糕造型"); } @Override protected void apply() { System.out.println("芝士蛋糕塗抹"); } @Override protected void brake() { System.out.println("芝士蛋糕烘焙"); } } class MouseCake extends AbstractCake { @Override protected void shape() { System.out.println("慕斯蛋糕造型"); } @Override protected void apply() { System.out.println("慕斯蛋糕塗抹"); } @Override protected void brake() { System.out.println("慕斯蛋糕烘焙"); } }
這樣一來,不但可以批量生產三種蛋糕,而且如果日后有擴展,只需要繼承抽象蛋糕方法就可以了,十分方便,小明天天生意做得越來越賺錢。突然有一天,小明看到對面店鋪的蛋糕店賣的一種最簡單的小蛋糕銷量很好,這種蛋糕就是簡單烘烤成型就可以賣,並不需要塗抹什么食材,由於制作簡單銷售量大,那家店靠這個品種賺了許多錢,於是小明也想要生產這種蛋糕。但是小明發現了一個問題,抽象蛋糕是定義了抽象的塗抹方法的,也就是說擴展的這種蛋糕是必須要實現塗抹方法,這就很雞兒蛋疼了。思來想去,小明不得其中三昧,於是就去問他師傅,他師傅疾言厲色:不帶鈎子方法的模板都是耍流氓!小明就仿佛吃了一顆九轉大還丹,簡直是茅塞頓開,於是他回去做了這么個修改
abstract class AbstractCake{ protected boolean shouldApply(){ return true; } protected abstract void shape(); protected abstract void apply(); protected abstract void brake(); public final void run(){ this.shape(); if(this.shouldApply()){ this.apply(); } this.brake(); } }
然后做小蛋糕的時候通過flag來控制是否塗抹
class SmallCake extends AbstractCake { private boolean flag = false; public void setFlag(boolean shouldApply){ flag = shouldApply; } @Override protected boolean shouldApply() { return this.flag; } @Override protected void shape() { System.out.println("小蛋糕造型"); } @Override protected void apply() { System.out.println("小蛋糕塗抹"); } @Override protected void brake() { System.out.println("小蛋糕烘焙"); } }
雖然這里有模板方法,但是通過鈎子方法還是能夠影響到模板方法的執行(不是影響它的邏輯)。小明又開開心心做起了生意。。