設(shè)計(jì)模式——模版方法模式

在閻宏博士的《JAVA與模式》一書(shū)中開(kāi)頭是這樣描述模板方法(Template Method)模式的:模板方法模式是類的行為模式。準(zhǔn)備一個(gè)抽象類,將部分邏輯以具體方法以及具體構(gòu)造函數(shù)的形式實(shí)現(xiàn),然后聲明一些抽象方法來(lái)迫使子類實(shí)現(xiàn)剩余的邏輯。不同的子類可以以不同的方式實(shí)現(xiàn)這些抽象方法,從而對(duì)剩余的邏輯有不同的實(shí)現(xiàn)。這就是模板方法模式的用意。

在模版方法模式中,通過(guò)在模版抽象類中定義一個(gè)操作的算法骨架,將一些步驟抽取封裝到具體的抽象方法中,強(qiáng)迫子類進(jìn)行按需要重寫(xiě)實(shí)現(xiàn)方法,這樣使得在使用的時(shí)候,子類可以不改變算法結(jié)構(gòu)即可重新定義算法的特定步驟。模版方法模式是基于繼承代碼復(fù)用的基本技術(shù)。

模版方法模式結(jié)構(gòu)

模版方法模式UML

TemplateMethod.png

模版方法模式涉及的角色

  • 抽象模板角色(AbstractTemplate):抽象模版類,用來(lái)定義算法的基本骨架,同時(shí)定義一個(gè)或多個(gè)抽象操作,這些操作由子類進(jìn)行實(shí)現(xiàn)。
  • 具體模板角色(ConcreteTemplate):具體模板角色,用來(lái)實(shí)現(xiàn)算法骨架中的某些步驟,完成與特定子類相關(guān)的功能。

案例演示

這里我們以登錄作為一個(gè)演示的例子,我們都知道,登錄模塊有會(huì)員登錄和普通用戶登錄,這兩塊在登錄權(quán)限處理上有所不同。

定義抽象模版登錄模塊

/**
 * 聲明一個(gè)抽象模版類
 * @author Iflytek_dsw
 *
 */
abstract class AbstractLogin {
    /**
     * 登錄的過(guò)程可以分為以下幾個(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ū)別,即子類重寫(xiě)父類預(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ì)員用戶登錄

通過(guò)上面的例子,我們可以看到,模板方法的核心就是固定算法的骨架結(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ù)用性,通過(guò)將公共的方法集中在模板類中,將公共不同部分抽取出來(lái)放到子類中實(shí)現(xiàn)達(dá)到復(fù)用的效果。
  • 擴(kuò)展性比較好,封裝不變的,擴(kuò)展可變部分。
  • 易于維護(hù)

缺點(diǎn)

  • 骨架固定,升級(jí)不易。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容