什么是模板方法呢?我們先回想以下SQL保存的例子,這個(gè)例子要 求我們能夠同時(shí)處理三種類(lèi)型的SQL語(yǔ)句保存文件:XML格式的文件,Properties格式文件和普通的文本格式的文件。不論那種格式的文件都要求能 夠提供根據(jù)SQL語(yǔ)句名字獲得SQL語(yǔ)句的方法。我們可以這樣子設(shè)計(jì):

public class AbstractSqlManager {

     private Map sqlMap ;

     public AbstractSqlManager(String filePath) {

         sqlMap = initSqlMap(filePath)

     }

     

     public String getSql(String key) {

         return (String)sqlMap.get(key);

     } 

     

     public abstract Map initSqlMap(String filePath);

 

public class XmlSqlManager extends AbstractSqlMamager {

     public Map initSqlMap(String filePath) {

         // 解析XML文件將SQL語(yǔ)句,以SQL語(yǔ)句的名字為Key,放在sqlMap中。

      }

}

 

public class PropertiesSqlManager extends AbstractSqlMamager {

     public Map initSqlMap(String filePath) {

         // 解析Properties文件將SQL語(yǔ)句,以SQL語(yǔ)句的名字為Key,放在sqlMap中。

      }

}

public class TextSqlManager extends AbstractSqlMamager {

     public Map initSqlMap(String filePath) {

         // 解析Text文件將SQL語(yǔ)句,以SQL語(yǔ)句的名字為Key,放在sqlMap中。

      }

}

 

參看上述的代碼,在AbstractSqlManager 中,因?yàn)榭赡芴幚淼奈募膬?nèi)容不同,所以將解析不同代碼的方法實(shí)現(xiàn)放在了具體的類(lèi)(XmlSqlManager ,PropertiesSqlManager 和TextSqlManager )中,只在AbstractSqlManager中實(shí)現(xiàn)了getSql方法。

 

我們?cè)趤?lái)考慮三個(gè)具體的實(shí)現(xiàn)類(lèi),在這些類(lèi)實(shí)現(xiàn)的時(shí)候,需要從AbstractSqlManager集成,所以必須實(shí)現(xiàn)initSqlMap這個(gè)方法,并且必須按照AbstractSqlManager中定義的格式(模板)來(lái)實(shí)現(xiàn)。

 

這樣可以稱(chēng)initSqlMap為模板方法,也可以稱(chēng)上述的設(shè)計(jì)為模板方法。

 

模板方法設(shè)計(jì)的好處有那些呢?

第一,也是繼承的好處,可以重用代碼

     如上述的例子,使用了模板方法之后,可以將公共的方法和流程在基類(lèi)中編寫(xiě),這樣可以重用這些代碼。(關(guān)于繼承和組合重用代碼的問(wèn)題參看另外的相關(guān)討論)

第二,可以靈活的對(duì)應(yīng)變更

     因?yàn)槭褂昧四0宸椒ǎ韵嗤牟僮骺梢栽诨?lèi)中 完成,具體的不同實(shí)現(xiàn)可以在具體類(lèi)中完成。所以首先有了變更修改的范圍很容易確定,如果是通用的操作則需要在基類(lèi)中完成,例如initSqlMap之前需 要使用日志記錄文件的信息。如果是特殊的操作則需要在具體類(lèi)中完成,例如XML文件格式發(fā)生了變更。

     

第三,規(guī)范處理流程(例如有三個(gè)模板方法)

     使用模板方法可以規(guī)范處理流程,例如要對(duì)輸入的數(shù)進(jìn)行相關(guān)的操作,我們可以定義這樣的幾個(gè)過(guò)程,(1)數(shù)據(jù)格式校驗(yàn)(2)數(shù)據(jù)邏輯校驗(yàn)(3)預(yù)處理(4)處理(5)處理輸出值(6)結(jié)束

     我們可以定義這樣子一個(gè)基類(lèi),包含需要的模板方法:

public class BaseTarget{

     public void execute(InputVO vo) throw ExecuteException {

         try {

                 formatCheck(vo);

                 logicCheck(vo);

                 preProcess(vo);

                 OutputVO out = process(vo);

                 formatCheck(out);

 

         } catch(FormatException ex) {

             // 異常處理

         } catch(LogicException ex) {

             // 異常處理 

         } catch(PreProcessExceptionex) {

              // 異常處理

         } catch(ProcessExceptionex) {

              // 異常處理

         } catch(PostProcessExceptionex) {

              // 異常處理

         } 

     }

 

     public abstract void formatCheck(InputVO vo) throw FormatException ;

 

     public abstract void logicCheck(InputVO vo) throw LogicException ;

 

     public abstract void preProcess(InputVO vo) throw PreProcessException;

 

     public abstract OutputVO process(InputVO vo) throw ProcessException;

 

     public abstract void postProcess(OutputVO vo) throw PostProcessException;

}

 

通過(guò)上述基類(lèi)的定義,我們規(guī)定了子類(lèi)型的處理內(nèi)容(五個(gè)需要實(shí)現(xiàn)的抽象方法)和處理的順序(按照execute方法定義的處理順序執(zhí)行)。

 



ExtJS教程- Hibernate教程-Struts2 教程-Lucene教程