第10章 考題抄錯(cuò)會(huì)做也白搭--模板方法模式

重復(fù)=易錯(cuò)+難改

場(chǎng)景:學(xué)生抄老師寫在黑板上的題目,然后再做答案。

每個(gè)同學(xué)抄的試卷非常類似,除了答案不同,沒什么不一樣,如果每個(gè)同學(xué)抄的試卷是一個(gè)類,這樣寫容易錯(cuò),又難以維護(hù)。如果老師突然要改題目,每個(gè)人都需要改代碼,如果有人抄錯(cuò),更是大問題。
應(yīng)該抽象出一個(gè)父類,讓兩個(gè)子類繼承,公共的試題代碼寫在父類當(dāng)中。
既然用了繼承,并且肯定這個(gè)繼承有意義,就應(yīng)該要成為子類的模板,所有重復(fù)的代碼都應(yīng)該上升到父類去,而不是讓每個(gè)子類都去重復(fù)。
當(dāng)要完成某一細(xì)節(jié)層次一致的一個(gè)過程或一系列步驟,但其個(gè)別步驟在更詳細(xì)的層次上的實(shí)現(xiàn)可能不同時(shí),通??紤]用模板方法模式來處理。

基于上面的場(chǎng)景,可以用以下代碼實(shí)現(xiàn):

父類

public abstract class TestPaper {

    public void question1() {
        print("試題1");
        print("答案:" + answer1());
    }

    /**
     * 答案的方法目的是給繼承的子類重寫
     * 因?yàn)檫@里每個(gè)人的答案都是不同的
     * @return
     */
    protected abstract String answer1();

    public void question2() {
        print("試題2");
        print("答案:" + answer2());
    }

    protected abstract String answer2();
}

子類A

public class TestPaperA extends TestPaper {

    /**
     * 重寫父類的方法
     * @return
     */
    @Override
    protected String answer1() {
        return "A";
    }

    @Override
    protected String answer2() {
        return "B";
    }
}

子類B

public class TestPaperB extends TestPaper {

    @Override
    protected String answer1() {
        return "B";
    }

    @Override
    protected String answer2() {
        return "C";
    }
}

測(cè)試代碼

public class Test {

    public static void main(String[] args) {
        print("學(xué)生A的試卷");
        //將子類變量聲明成父類,利用多態(tài)性,實(shí)現(xiàn)代碼的復(fù)用
        TestPaper a = new TestPaperA();
        a.question1();
        a.question2();

        print("學(xué)生B的試卷");
        TestPaper b = new TestPaperB();
        b.question1();
        b.question2();
    }
}

模板方法模式

模板方法模式,定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。[DP]

模板方法模式(TemplateMethod)結(jié)構(gòu)圖

圖片.png

AbstractClass是抽象類,其實(shí)也就是一個(gè)抽象模板,定義并實(shí)現(xiàn)了一個(gè)模板方法。這個(gè)模板方法一般是一個(gè)具體方法,它給出了一個(gè)頂級(jí)邏輯的骨架,而邏輯的組成步驟在相應(yīng)的抽象操作中,推遲到子類實(shí)現(xiàn)。頂級(jí)邏輯也有可能調(diào)用一些具體方法。

public abstract class AbstractClass {

    /**
     * 一些抽象行為,放到子類去實(shí)現(xiàn)
     */
    public abstract void primitiveOperation1();
    public abstract void primitiveOperation2();

    /**
     * 模板方法,給出了邏輯的骨架
     * 而邏輯的組成是一些相應(yīng)的抽象操作,他們都推遲到子類實(shí)現(xiàn)
     */
    public void templateMethod(){
        primitiveOperation1();
        primitiveOperation2();
    }
}

ConcreteClass,實(shí)現(xiàn)父類所定義的一個(gè)或多個(gè)抽象方法。每一個(gè)AbstractClass都可以有任意多個(gè)ConcreteClass與之對(duì)應(yīng),而每一個(gè)ConcreteClass都可以給出這些抽象方法(也就是頂級(jí)邏輯的組成步驟)的不同實(shí)現(xiàn),從而使得頂級(jí)邏輯的實(shí)現(xiàn)各不相同。

public class ConcreteClass extends AbstractClass {
    @Override
    public void primitiveOperation1() {
        print("具體類1方法1的具體實(shí)現(xiàn)");
    }

    @Override
    public void primitiveOperation2() {
        print("具體類1方法2的具體實(shí)現(xiàn)");
    }
}

測(cè)試代碼

public class Test2 {

    public static void main(String[] args) {
        AbstractClass c = new ConcreteClass();
        c.templateMethod();
    }

}

模板方法模式特點(diǎn)

模板方法模式是通過把不變行為搬移到超類,去除子類中的重復(fù)代碼來體現(xiàn)它的優(yōu)勢(shì)。模板方法模式就是提供了一個(gè)很好的代碼復(fù)用平臺(tái)。當(dāng)不變的和可變的行為在方法的子類實(shí)現(xiàn)中混合在一起的時(shí)候,不變的行為就會(huì)在子類中重復(fù)出現(xiàn)。通過模板方法模式把這些行為搬移到單一的地方,就幫助子類擺脫重復(fù)的不變行為的糾纏。

?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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