大話設計模式筆記(八)の模板方法模式

舉個栗子

問題描述

小時候數學老師的隨堂測驗,都是在黑板上抄題目,而後再做答案。寫一個抄題目的程序。算法

簡單實現

學生甲抄的試卷

/**
 * 學生甲抄的試卷
 * Created by callmeDevil on 2019/7/14.
 */
public class TestPaperA {

    // 試題1
    public void testQuestion1(){
        System.out.println("路飛在頂上戰爭以後,修煉了多久? a.3天 b.2年 c.2天 d.3年");
        System.out.println("答案:b");
    }

    // 試題2
    public void testQuestion2(){
        System.out.println("鳴人是第幾代火影? a.六代 b.七代 c.八代 d.九代");
        System.out.println("答案:b");
    }

}

學生乙抄的試卷

/**
 * 學生乙抄的試卷
 * Created by callmeDevil on 2019/7/14.
 */
public class TestPaperB {

    // 試題1
    public void testQuestion1(){
        System.out.println("路飛在頂上戰爭以後,修煉了多久? a.3天 b.2年 c.2天 d.3年");
        System.out.println("答案:a");
    }

    // 試題2
    public void testQuestion2(){
        System.out.println("鳴人是第幾代火影? a.六代 b.七代 c.八代 d.九代");
        System.out.println("答案:a");
    }

}

測試

public class Test {

    public static void main(String[] args) {
        System.out.println("學生甲抄的試卷:");
        TestPaperA studentA = new TestPaperA();
        studentA.testQuestion1();
        studentA.testQuestion2();

        System.out.println("學生乙抄的試卷:");
        TestPaperB studentB = new TestPaperB();
        studentB.testQuestion1();
        studentB.testQuestion2();
    }

}

測試結果

學生甲抄的試卷:
路飛在頂上戰爭以後,修煉了多久? a.3天 b.2年 c.2天 d.3年
答案:b
鳴人是第幾代火影? a.六代 b.七代 c.八代 d.九代
答案:b
學生乙抄的試卷:
路飛在頂上戰爭以後,修煉了多久? a.3天 b.2年 c.2天 d.3年
答案:a
鳴人是第幾代火影? a.六代 b.七代 c.八代 d.九代
答案:a

存在問題

兩個學生抄試卷都很是相似,除了答案不一樣,沒什麼不同,這樣又容易錯,又難以維護。所以老師出一份試卷,打印多份,讓學生填寫答案就能夠了。應該把試題和答案分離,抽出一個父類,讓兩個子類繼承它,公共的試題代碼寫到父類當中就好了。ide

提煉代碼

試題父類

/**
 * 試題父類-動漫考題
 * Created by callmeDevil on 2019/7/14.
 */
public class TestPaper {

    // 試題1
    public void testQuestion1(){
        System.out.println("路飛在頂上戰爭以後,修煉了多久? a.3天 b.2年 c.2天 d.3年");
    }

    // 試題2
    public void testQuestion2(){
        System.out.println("鳴人是第幾代火影? a.六代 b.七代 c.八代 d.九代");
    }
    
}

學生甲抄的試卷-版本2

/**
 * 學生甲抄的試卷-版本2
 * Created by callmeDevil on 2019/7/14.
 */
public class TestPaperA2 extends TestPaper{

    @Override
    public void testQuestion1() {
        super.testQuestion1();
        System.out.println("答案:b");
    }

    @Override
    public void testQuestion2() {
        super.testQuestion2();
        System.out.println("答案:b");
    }
}

學生乙抄的試卷-版本2

/**
 * 學生乙抄的試卷-版本2
 * Created by callmeDevil on 2019/7/14.
 */
public class TestPaperB2 extends TestPaper{

    @Override
    public void testQuestion1(){
        super.testQuestion1();
        System.out.println("答案:a");
    }

    @Override
    public void testQuestion2(){
        super.testQuestion2();
        System.out.println("答案:a");
    }

}

客戶端測試代碼與測試結果此處省略,同上述簡單實現。測試

存在的問題

  • 既然用了繼承,而且確定這個繼承有意義,就應該要成爲子類的模板,全部重複的代碼都應該要上升到父類去,而不是讓每一個子類都去重複
  • 當咱們要完成在某一個細節層次一致的一個過程或一系列步驟,但其個別步驟在更詳細的層次上的實現可能不一樣時,咱們一般考慮用模板方法模式來處理
  • 在上面提煉的代碼中,每一個學生只是輸出的答案不一樣,其餘所有都是同樣的,應該在此處改爲一個虛方法,讓每一個子類去重寫便可

模板方法模式

定義

定義一個操做中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類能夠不改變一個算法的結構便可重定義該算法的某些特定的步驟。code

UML圖

代碼實現

模板方法父類-動漫考題

/**
 * 模板方法父類-動漫考題
 * Created by callmeDevil on 2019/7/14.
 */
public abstract class TestPaper {

    // 試題1
    public void testQuestion1(){
        System.out.println("路飛在頂上戰爭以後,修煉了多久? a.3天 b.2年 c.2天 d.3年");
        System.out.println("答案:" + answer1());//改爲一個虛方法,下同
    }

    // 試題2
    public void testQuestion2(){
        System.out.println("鳴人是第幾代火影? a.六代 b.七代 c.八代 d.九代");
        System.out.println("答案:" + answer2());
    }

    // 此方法的目的就是給繼承的子類重寫,由於這裏每一個人的答案都是不一樣的
    public abstract String answer1();
    public abstract String answer2();

}

學生甲抄的試卷-模板方法實現

/**
 * 學生甲抄的試卷-模板方法實現
 * Created by callmeDevil on 2019/7/14.
 */
public class TestPaperA3 extends TestPaper{

    @Override
    public String answer1() {
        return "b";
    }

    @Override
    public String answer2() {
        return "b";
    }

}

學生乙抄的試卷-模板方法實現

/**
 * 學生乙抄的試卷-模板方法實現
 * Created by callmeDevil on 2019/7/14.
 */
public class TestPaperB3 extends TestPaper{

    @Override
    public String answer1() {
        return "a";
    }

    @Override
    public String answer2() {
        return "a";
    }

}

模板方法測試

/**
 * 模板方法測試
 * Created by callmeDevil on 2019/7/14.
 */
public class Test3 {

    public static void main(String[] args) {
        System.out.println("學生甲抄的試卷:");
        // 將子類變量的聲明改爲父類,利用多態性實現了代碼的複用
        TestPaper studentA = new TestPaperA3();
        studentA.testQuestion1();
        studentA.testQuestion2();

        System.out.println("學生乙抄的試卷:");
        TestPaper studentB = new TestPaperB3();
        studentB.testQuestion1();
        studentB.testQuestion2();
    }

}

測試結果是一致的,此處再也不貼出。blog

總結

  • 模板方法模式是經過把不變的行爲搬移到父類,去除子類中重複的代碼來體現它的優點
  • 模板方法模式就是提供了一個很好的代碼複用平臺
  • 當不變的和可變的行爲在方法的子類實現中混合在一塊兒的時候,不變的行爲就會在子類中重複出現。咱們經過模板方法模式把這些行爲搬移到單一的地方,這樣就幫助子類擺脫重複的不變行爲的糾纏。
相關文章
相關標籤/搜索