什么是模板方法呢?我們先回想以下SQL保存的例子,這個例子要
求我們能夠同時處理三種類型的SQL語句保存文件:XML格式的文件,Properties格式文件和普通的文本格式的文件。不論那種格式的文件都要求能
夠提供根據SQL語句名字獲得SQL語句的方法。我們可以這樣子設計:
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語句,以SQL語句的名字為Key,放在sqlMap中。
}
}
public class PropertiesSqlManager extends AbstractSqlMamager {
public Map initSqlMap(String filePath) {
// 解析Properties文件將SQL語句,以SQL語句的名字為Key,放在sqlMap中。
}
}
public class TextSqlManager extends AbstractSqlMamager {
public Map initSqlMap(String filePath) {
// 解析Text文件將SQL語句,以SQL語句的名字為Key,放在sqlMap中。
}
}
參看上述的代碼,在AbstractSqlManager
中,因為可能處理的文件的內容不同,所以將解析不同代碼的方法實現放在了具體的類(XmlSqlManager
,PropertiesSqlManager 和TextSqlManager
)中,只在AbstractSqlManager中實現了getSql方法。
我們在來考慮三個具體的實現類,在這些類實現的時候,需要從AbstractSqlManager集成,所以必須實現initSqlMap這個方法,并且必須按照AbstractSqlManager中定義的格式(模板)來實現。
這樣可以稱initSqlMap為模板方法,也可以稱上述的設計為模板方法。
模板方法設計的好處有那些呢?
第一,也是繼承的好處,可以重用代碼
如上述的例子,使用了模板方法之后,可以將公共的方法和流程在基類中編寫,這樣可以重用這些代碼。(關于繼承和組合重用代碼的問題參看另外的相關討論)
第二,可以靈活的對應變更
因為使用了模板方法,所以相同的操作可以在基類中
完成,具體的不同實現可以在具體類中完成。所以首先有了變更修改的范圍很容易確定,如果是通用的操作則需要在基類中完成,例如initSqlMap之前需
要使用日志記錄文件的信息。如果是特殊的操作則需要在具體類中完成,例如XML文件格式發生了變更。
第三,規范處理流程(例如有三個模板方法)
使用模板方法可以規范處理流程,例如要對輸入的數進行相關的操作,我們可以定義這樣的幾個過程,(1)數據格式校驗(2)數據邏輯校驗(3)預處理(4)處理(5)處理輸出值(6)結束
我們可以定義這樣子一個基類,包含需要的模板方法:
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;
}
通過上述基類的定義,我們規定了子類型的處理內容(五個需要實現的抽象方法)和處理的順序(按照execute方法定義的處理順序執行)。
ExtJS教程-
Hibernate教程-
Struts2 教程-
Lucene教程