又叫模板方法模式,在一個(gè)方法中定義一個(gè)算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變算法結(jié)構(gòu)的情冴下,重新定義算法中的某些步驟。
我們使用沖泡咖啡和沖泡茶的例子
加工流程:
咖啡沖泡法:1.把水煮沸、2.用沸水沖泡咖啡、3.把咖啡倒進(jìn)杯子、4.加糖和牛奶
茶沖泡法: 1.把水煮沸、2.用沸水沖泡茶葉、3.把 茶 倒進(jìn)杯子、4.加蜂蜜
一、創(chuàng)建一個(gè)創(chuàng)模板(抽象)類
package com.kaishengit.beverage;public abstract class Beverage { /** * 沖泡咖啡或茶...流程 */ public final void create(){ boilWater();//把水煮沸 brew();//用沸水沖泡... pourInCup();//把...倒進(jìn)杯子 addCoundiments();//加... } public abstract void addCoundiments(); public abstract void brew(); public void boilWater() { System.out.); } public void pourInCup() { System.out.println("倒進(jìn)杯子"); }}
2>創(chuàng)建一個(gè)咖啡類(Coffee)和茶(Tea)類,都繼承Beverage抽象類
1.咖啡(Coffee)
package com.kaishengit.beverage;public class Coffee extends Beverage{ @Override public void addCoundiments() { System.out.println("添加糖和牛奶"); } @Override public void brew() { System.out.println("用水沖咖啡"); }}
2.茶(Tea)
package com.kaishengit.beverage;public class Tea extends Beverage{ @Override public void addCoundiments() { System.out.println("添加蜂蜜"); } @Override public void brew() { System.out.println("用水沖茶"); }}
3.我們測(cè)試一下:
package com.kaishengit.beverage;public class Test { public static void main(String[] args) { Coffee coffee = new Coffee(); coffee.create();//沖泡咖啡 //Tea tea = new Tea();//沖泡茶 //tea.create(); }}
運(yùn)行結(jié)果:
-----------------------------------
煮開水
用水沖咖啡
倒進(jìn)杯子
添加糖和牛奶
-----------------------------------
在模版模式中使用掛鉤(hook)
存在一個(gè)空實(shí)現(xiàn)的方法,我們稱這種方法為”hook”。子類可以視情況來(lái)決定是否要覆蓋它。
1>我們對(duì)模板類(Beverage)進(jìn)行修改
package com.kaishengit.beverage;public abstract class Beverage { /** * 沖泡咖啡或茶...流程 */ public final void create(){ boilWater();//把水煮沸 brew();//用沸水沖泡... pourInCup();//把...倒進(jìn)杯子 addCoundiments();//加... hook();//掛鉤 } //空實(shí)現(xiàn)方法 public void hook(){} public abstract void addCoundiments(); public abstract void brew(); public void boilWater() { System.out.println("煮開水"); } public void pourInCup() { System.out.println("倒進(jìn)杯子"); }}
2>假如我們搞活動(dòng),喝一杯咖啡送一杯,修改咖啡(Coffee)類
package com.kaishengit.beverage;public class Coffee extends Beverage{ @Override public void addCoundiments() { System.out.println("添加糖和牛奶"); } @Override public void brew() { System.out.println("用水沖咖啡"); } /** * 掛鉤 */ @Override public void hook() { System.out.println("再來(lái)一杯"); }}
3>使用上面的測(cè)試類
運(yùn)行結(jié)果:
--------------------------------
煮開水
用水沖咖啡
倒進(jìn)杯子
添加糖和牛奶
再來(lái)一杯
--------------------------------
結(jié)果中有“再來(lái)一杯”...
我們也可以這樣使用掛鉤,讓其決定里面的代碼是否執(zhí)行
1>我們對(duì)模板類(Beverage)進(jìn)行修改
package com.kaishengit.beverage;public abstract class Beverage { /** * 沖泡咖啡或茶...流程 */ public final void create(){ boilWater();//把水煮沸 brew();//用沸水沖泡... pourInCup();//把...倒進(jìn)杯子 //掛鉤決定是否添加配料 if(hook()){ addCoundiments();//加... } //hook(); } /** * 默認(rèn)添加配料 * @return */ public boolean hook() { return true; } //public void hook(){} public abstract void addCoundiments(); public abstract void brew(); public void boilWater() { System.out.println("煮開水"); } public void pourInCup() { System.out.println("倒進(jìn)杯子"); }}
2>我們對(duì)Coffee類進(jìn)行修改,讓其不添加配料
package com.kaishengit.beverage;public class Coffee extends Beverage{ @Override public void addCoundiments() { System.out.println("添加糖和牛奶"); } @Override public void brew() { System.out.println("用水沖咖啡"); } /** * 有的客人不喜歡加配料 */ @Override public boolean hook() { return false; } /*@Override public void hook() { System.out.println("再來(lái)一杯"); }*/}
3>還是使用上面的測(cè)試類
運(yùn)行結(jié)果:
------------------------------------------------------
煮開水
用水沖咖啡
倒進(jìn)杯子
------------------------------------------------------
運(yùn)行結(jié)果中沒(méi)有添加配料
關(guān)于模板模式
1>模板模式定義了算法的步驟,把這些步驟的實(shí)現(xiàn)延遲到子類
2>模板模式為我們提供了一個(gè)代碼復(fù)用的技巧
3>模板抽象類中可以定義具體方法、抽象方法和鉤子方法
4>為了防止子類改變模板中的算法,可以將模板方法聲明為final
5>鉤子是一種方法,它在抽象類中不做事,或只做默認(rèn)的事,子類可以選擇要不要實(shí)現(xiàn)它
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注