在閻宏博士的《JAVA與模式》一書中開頭是這樣描述模板方法(Template Method)模式的:模板方法模式是類的行為模式。準(zhǔn)備一個(gè)抽象類愉豺,將部分邏輯以具體方法以及具體構(gòu)造函數(shù)的形式實(shí)現(xiàn)允乐,然后聲明一些抽象方法來迫使子類實(shí)現(xiàn)剩余的邏輯矮嫉。不同的子類可以以不同的方式實(shí)現(xiàn)這些抽象方法,從而對(duì)剩余的邏輯有不同的實(shí)現(xiàn)牍疏。這就是模板方法模式的用意蠢笋。
在模版方法模式中,通過在模版抽象類中定義一個(gè)操作的算法骨架鳞陨,將一些步驟抽取封裝到具體的抽象方法中昨寞,強(qiáng)迫子類進(jìn)行按需要重寫實(shí)現(xiàn)方法,這樣使得在使用的時(shí)候厦滤,子類可以不改變算法結(jié)構(gòu)即可重新定義算法的特定步驟援岩。模版方法模式是基于繼承代碼復(fù)用的基本技術(shù)。
模版方法模式結(jié)構(gòu)
模版方法模式UML
模版方法模式涉及的角色
- 抽象模板角色(AbstractTemplate):抽象模版類掏导,用來定義算法的基本骨架享怀,同時(shí)定義一個(gè)或多個(gè)抽象操作,這些操作由子類進(jìn)行實(shí)現(xiàn)趟咆。
- 具體模板角色(ConcreteTemplate):具體模板角色凹蜈,用來實(shí)現(xiàn)算法骨架中的某些步驟,完成與特定子類相關(guān)的功能忍啸。
案例演示
這里我們以登錄作為一個(gè)演示的例子,我們都知道履植,登錄模塊有會(huì)員登錄和普通用戶登錄计雌,這兩塊在登錄權(quán)限處理上有所不同。
定義抽象模版登錄模塊
/**
* 聲明一個(gè)抽象模版類
* @author Iflytek_dsw
*
*/
abstract class AbstractLogin {
/**
* 登錄的過程可以分為以下幾個(gè)步驟:
* 1玫霎、密碼加密凿滤;
* 2、用戶驗(yàn)證庶近;
*/
public void login(String userName, String pwd){
encryptPwd(pwd);
loginUser(userName,pwd);
}
protected abstract void loginUser(String userName, String pwd);
/**
* 密碼加密
* @param pwd
*/
private void encryptPwd(String pwd){
System.out.println("密碼加密");
}
}
在抽象登錄模塊中翁脆,我們定義了聲明了一個(gè)方法encryptPwd,同時(shí)聲明了一個(gè)loginUser的抽象函數(shù)鼻种。
定義具體的模板方法類
/**
* 普通用戶登錄
* @author Iflytek_dsw
*
*/
class NormalLogin extends AbstractLogin{
@Override
public void loginUser(String userName, String pwd) {
System.out.println("普通用戶登錄:"+ userName);
}
}
/**
* 會(huì)員用戶登錄
* @author Iflytek_dsw
*
*/
class MemberLogin extends AbstractLogin{
@Override
public void loginUser(String userName, String pwd) {
System.out.println("會(huì)員用戶登錄" + userName);
}
}
根據(jù)權(quán)限角色不同反番,登錄的方法有所區(qū)別,即子類重寫父類預(yù)留的模板方法。
客戶端
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
AbstractLogin normalLogin = new NormalLogin();
AbstractLogin memberLogin = new MemberLogin();
normalLogin.login("andoter的學(xué)習(xí)筆記", "dsw123");
memberLogin.login("Andoter學(xué)習(xí)筆記", "andoter123");
}
}
執(zhí)行結(jié)果
密碼加密
普通用戶登錄
密碼加密
會(huì)員用戶登錄
通過上面的例子罢缸,我們可以看到篙贸,模板方法的核心就是固定算法的骨架結(jié)構(gòu),它的UML圖跟策略模式非常相似枫疆,本質(zhì)上這兩種模式還是有很大差異的爵川。策略模式側(cè)重的不同的策略,模板方法模式側(cè)重的是某個(gè)處理流程中的關(guān)鍵節(jié)點(diǎn)代碼不確定息楔,范圍比策略模式小寝贡。
模板方法中的方法
根據(jù)上面的介紹,模板方法中的方法可以分為兩大類:模板方法和基本方法值依。
模板方法
- 一個(gè)模板方法是定義在抽象類中的圃泡,把基本操作方法組合在一起形成一個(gè)總算法或一個(gè)總行為的方法。
- 一個(gè)抽象類可以有任意多個(gè)模板方法鳞滨,而不限于一個(gè)洞焙。每一個(gè)模板方法都可以調(diào)用任意多個(gè)具體方法。
基本方法
- 抽象方法:一個(gè)抽象方法由抽象類聲明拯啦,由具體子類實(shí)現(xiàn)澡匪。在Java語(yǔ)言里抽象方法以abstract關(guān)鍵字標(biāo)示。
- 具體方法:一個(gè)具體方法由抽象類聲明并實(shí)現(xiàn)褒链,而子類并不實(shí)現(xiàn)或置換唁情。
- 鉤子方法:一個(gè)鉤子方法由抽象類聲明并實(shí)現(xiàn),而子類會(huì)加以擴(kuò)展甫匹。通常抽象類給出的實(shí)現(xiàn)是一個(gè)空實(shí)現(xiàn)甸鸟,作為方法的默認(rèn)實(shí)現(xiàn)。
模板方法優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 良好的復(fù)用性兵迅,通過將公共的方法集中在模板類中抢韭,將公共不同部分抽取出來放到子類中實(shí)現(xiàn)達(dá)到復(fù)用的效果。
- 擴(kuò)展性比較好恍箭,封裝不變的刻恭,擴(kuò)展可變部分。
- 易于維護(hù)
缺點(diǎn)
- 骨架固定扯夭,升級(jí)不易鳍贾。