開(kāi)通VIP,暢享免費電子書(shū)等14項超值服
首頁(yè)
好書(shū)
留言交流
下載APP
聯(lián)系客服
2013.12.26
模板模式(Template Patern),是在一個(gè)方法中定義了一個(gè)算法的骨架,而將一些步驟延遲到子類(lèi)中。模板方法中使得子類(lèi)可以在不改變算法結構的情況下,重新定義算法中的某些步驟。
模板就是一個(gè)方法,這個(gè)方法將算法定義成一組步驟,為了不被子類(lèi)改變,這個(gè)方法通常被限制為final類(lèi)型。另外還有一個(gè)鉤子(hook)的概念,所謂的“鉤子”就是默認不做事的方法,這個(gè)方法在抽象類(lèi)中是不實(shí)現的或者為空,子類(lèi)可以決定是否要覆蓋它,自然,這個(gè)方法的調用是在“模板”方法中。
當子類(lèi)必須提供“模板”中某個(gè)方法的實(shí)現時(shí),這個(gè)方法就在父類(lèi)中定義為抽象方法;如果這個(gè)方法是可選的,或者對于子類(lèi)的實(shí)現不重要的時(shí)候,就使用鉤子來(lái)控制。使用鉤子,可以讓子類(lèi)對模板方法中即將發(fā)生的步驟做出反應。
來(lái)個(gè)示例,其實(shí)網(wǎng)上很多例子了,做飯的例子、燒菜的例子、泡咖啡泡茶的例子,等等,都是為了說(shuō)明模板模式的用法。在這里就不說(shuō)那些例子了,自己寫(xiě)個(gè)玩完,純粹練手。
現在安卓手機應用非常多,但是都需要首先安裝到手機上才能使用,在安裝的時(shí)候,我們抽象一下,一般需要這么幾個(gè)步驟:申請安裝權限、創(chuàng )建相應目錄、注冊服務(wù)、選擇是否開(kāi)機啟動(dòng)等。我們以這個(gè)為例子,說(shuō)明下模板模式的使用。
首先是創(chuàng )建個(gè)抽象類(lèi),用于描述所有的安裝步驟:
1 package org.scott.template; 2 /** 3 * @author Scott 4 * @date 2013年12月25日 5 * @description 6 */ 7 public abstract class Setup { 8 public final void setup(){ 9 getAuthority();10 createDir();11 registerService();12 13 if(isAutoStart()){14 autoStart();15 }16 17 printMsg();18 }19 20 public abstract void getAuthority();21 public abstract void createDir();22 public abstract void registerService();23 24 public boolean isAutoStart(){25 return false;26 };27 28 public void printMsg(){29 System.out.println("The app has set up over.");30 }31 32 private void autoStart(){33 System.out.println("The app will start automatically, has add it to the auto-start list.");34 }35 }
是否開(kāi)機啟動(dòng)這個(gè)就是鉤子,由子類(lèi)決定。
下面是具體的一個(gè)實(shí)現,有道筆記的安裝:
1 package org.scott.template; 2 /** 3 * @author Scott 4 * @date 2013年12月25日 5 * @description 6 */ 7 public class YoudaoSetup extends Setup { 8 9 @Override10 public void getAuthority() {11 System.out.println("Has got the set up authority.");12 }13 14 @Override15 public void createDir() {16 System.out.println("Create Youdao directory.");17 }18 19 @Override20 public void registerService() {21 System.out.println("Register the Youdao service.");22 }23 24 @Override25 public boolean isAutoStart() {26 return true;27 }28 29 }
這里的實(shí)現,我們覆寫(xiě)了isAutoStart方法,將其設置為true,將當前此軟件加入開(kāi)機自啟列表中。鉤子,可以在子類(lèi)中覆寫(xiě),也可以直接使用父類(lèi)中的默認實(shí)現。下面的QQ安裝,就是使用的默認實(shí)現:
1 package org.scott.template; 2 /** 3 * @author Scott 4 * @date 2013年12月25日 5 * @description 6 */ 7 public class QQSetup extends Setup { 8 9 @Override10 public void getAuthority() {11 System.out.println("Has got the set up authority.");12 }13 14 @Override15 public void createDir() {16 System.out.println("Create QQ directory.");17 }18 19 @Override20 public void registerService() {21 System.out.println("Register the QQ service.");22 }23 }
以上基本上就是抽象模板和具體模板的實(shí)現,模板方法實(shí)際上在子類(lèi)中都沒(méi)有修改,因為我們把它設置成了final型,子類(lèi)所修改的就是模板方法中的一些具體的實(shí)現算法,比如不同的軟件,它的安裝目錄、注冊的服務(wù)都是不同,我們把這些都作為抽象方法,子類(lèi)必須實(shí)現自己的特定方法。
寫(xiě)個(gè)測試類(lèi):
1 package org.scott.template; 2 /** 3 * @author Scott 4 * @date 2013年12月25日 5 * @description 6 */ 7 public class TemplateTest { 8 9 public static void main(String[] args) {10 Setup qqSetup = new QQSetup();11 Setup youdaoSetup = new YoudaoSetup();12 13 qqSetup.setup();14 System.out.println("\n---------------------------\n");15 youdaoSetup.setup();16 }17 18 }
測試結果:
1 Has got the set up authority. 2 Create QQ directory. 3 Register the QQ service. 4 The app has set up over. 5 6 --------------------------- 7 8 Has got the set up authority. 9 Create Youdao directory.10 Register the Youdao service.11 The app will start automatically, has add it to the auto-start list.12 The app has set up over.
通過(guò)上面的例子,我們可以看到,使用模板方式時(shí),有兩個(gè)角色:
(1)抽象模板角色:定義了一個(gè)或多個(gè)抽象操作,以便讓子類(lèi)實(shí)現,這些抽象操作稱(chēng)為基本操作。
(2)具體模板角色:實(shí)現父類(lèi)所定義的一個(gè)或多個(gè)抽象方法。
模板模式主要實(shí)現了代碼復用,符合開(kāi)放-封閉原則,因為引入了一個(gè)抽象類(lèi),所以如果具體實(shí)現過(guò)多的話(huà),類(lèi)之間的關(guān)系是復雜點(diǎn)。
微信登錄中...請勿關(guān)閉此頁(yè)面