今天我們來講一下模板方法模式。 一、案例 我們在上中學的時候,會有這麼一種場景,老師在黑板上寫測試題,讓我們自己抄到紙上做。相信不少小伙伴們都經歷過這種歲月,想想還是很懷念的呢。這種做測試的方式,對當時的我們來講,有一個最致命的痛苦,就是這個題目會做,但是TM抄錯了題目了,擦擦擦。相信不少小伙伴肯定 ...
今天我們來講一下模板方法模式。
一、案例
我們在上中學的時候,會有這麼一種場景,老師在黑板上寫測試題,讓我們自己抄到紙上做。相信不少小伙伴們都經歷過這種歲月,想想還是很懷念的呢。這種做測試的方式,對當時的我們來講,有一個最致命的痛苦,就是這個題目會做,但是TM抄錯了題目了,擦擦擦。相信不少小伙伴肯定會遇到過這種情況。
好,下麵我們就用簡單的控制台應用程式來模擬一下這個場景
1 /// <summary> 2 /// 學生A抄的測試題 3 /// </summary> 4 class TestPaperA 5 { 6 //第一題 7 public void TestQuestion1() 8 { 9 Console.WriteLine("第一題XXXXXXXXXXX"); 10 Console.WriteLine("A"); 11 } 12 //第二題 13 public void TestQuestion2() 14 { 15 Console.WriteLine("第二題XXXXXXXXXXX"); 16 Console.WriteLine("A"); 17 } 18 //第三題 19 public void TestQuestion3() 20 { 21 Console.WriteLine("第三題XXXXXXXXXXX"); 22 Console.WriteLine("B"); 23 } 24 } 25 /// <summary> 26 /// 學生B抄的測試題 27 /// </summary> 28 class TestPaperB 29 { 30 //第一題 31 public void TestQuestion1() 32 { 33 Console.WriteLine("第一題XXXXXXXXXXX"); 34 Console.WriteLine("C"); 35 } 36 //第二題 37 public void TestQuestion2() 38 { 39 Console.WriteLine("第二題XXXXXXXXXXX"); 40 Console.WriteLine("A"); 41 } 42 //第三題 43 public void TestQuestion3() 44 { 45 Console.WriteLine("第三題XXXXXXXXXXX"); 46 Console.WriteLine("B"); 47 } 48 }
客戶端:
1 public static void Main() 2 { 3 Console.WriteLine("學生甲抄的試卷:"); 4 TestPaperA studentA = new MyTest.TestPaperA(); 5 studentA.TestQuestion1(); 6 studentA.TestQuestion2(); 7 studentA.TestQuestion3(); 8 9 Console.WriteLine("學生乙抄的試卷:"); 10 TestPaperB studentB = new MyTest.TestPaperB(); 11 studentB.TestQuestion1(); 12 studentB.TestQuestion2(); 13 studentB.TestQuestion3(); 14 15 Console.Read(); 16 }
上述代碼很好的描述了當前的這個場景,下麵呢,我們來看一下這種寫法有哪些問題。
①A B 兩個同學,除了個別的答案不一樣之外,其他的都是一樣的。
②如果老師突然要改題目,那麼 A B 兩個同學都需要修改。
③萬一有哪個同學把題目抄錯了,那豈不是很糟糕了。
二、演繹
1、第一步演繹
針對上面的幾個問題,我們來分析一下,感覺最好的效果就是,老師出一份試卷,多列印幾份,發給學生,只讓學生填寫答案就可以了。
好,這樣,我們可以抽象出一個父類(試題),分別讓A B 兩個繼承這個父類,就可以了。代碼如下:
1 /// <summary> 2 /// 父類 試卷 3 /// </summary> 4 class TestPaper 5 { 6 public void TestQuestion1() 7 { 8 Console.WriteLine("第一題XXXXXXXXXXXX"); 9 } 10 public void TestQuestion2() 11 { 12 Console.WriteLine("第二題XXXXXXXXXXXX"); 13 } 14 public void TestQuestion3() 15 { 16 Console.WriteLine("第三題XXXXXXXXXXXX"); 17 } 18 }
1 /// <summary> 2 /// 發給B的試卷 3 /// </summary> 4 class TestPaperA :TestPaper 5 { 6 //第一題 7 public new void TestQuestion1() 8 { 9 base.TestQuestion1(); 10 Console.WriteLine("A"); 11 } 12 //第二題 13 public new void TestQuestion2() 14 { 15 base.TestQuestion2(); 16 Console.WriteLine("A"); 17 } 18 //第三題 19 public new void TestQuestion3() 20 { 21 base.TestQuestion3(); 22 Console.WriteLine("B"); 23 } 24 } 25 /// <summary> 26 /// 發給B的試卷 27 /// </summary> 28 class TestPaperB:TestPaper 29 { 30 //第一題 31 public new void TestQuestion1() 32 { 33 base.TestQuestion1(); 34 Console.WriteLine("C"); 35 } 36 //第二題 37 public new void TestQuestion2() 38 { 39 base.TestQuestion2(); 40 Console.WriteLine("A"); 41 } 42 //第三題 43 public new void TestQuestion3() 44 { 45 base.TestQuestion3(); 46 Console.WriteLine("B"); 47 } 48 }
客戶端
1 public static void Main() 2 { 3 Console.WriteLine("學生甲抄的試卷:"); 4 TestPaperA studentA = new MyTest.TestPaperA(); 5 studentA.TestQuestion1(); 6 studentA.TestQuestion2(); 7 studentA.TestQuestion3(); 8 9 Console.WriteLine("學生乙抄的試卷:"); 10 TestPaperB studentB = new MyTest.TestPaperB(); 11 studentB.TestQuestion1(); 12 studentB.TestQuestion2(); 13 studentB.TestQuestion3(); 14 15 Console.Read(); 16 }
嗯,我們看一下我們改進後的代碼還有什麼問題?
①每一個子類中都包含多個base. 還有 Console.WriteLine(),其實感覺除了ABCD答案之外,其他的都是重覆的。
既然用到了繼承,那麼,這個父類就應該成為一個模板,所有重覆的代碼都應該提升到父類中去。而不是去讓每個子類都去重覆。
如何實現呢?下麵就是我們要將的模板方法模式了。
當我們完成某一細節層次上一致的過程或步驟,但更深層次的細節不太一樣的情況下,我們可以考慮使用模板方法模式了。
好,下麵我們來看一下模板方法模式的寫法:
1 //抽象的父類 2 abstract class AbstractClass 3 { 4 //一些抽象的行為,放到子類去實現 5 public abstract void PrimitiveOperation1(); 6 public abstract void PrimitiveOperation2(); 7 8 //模板方法,給出了邏輯的骨架,邏輯的組成是一些相應的抽象操作,他們都到推遲到子類中去實現 9 public void TemplageMethod() 10 { 11 PrimitiveOperation1(); 12 PrimitiveOperation2(); 13 Console.WriteLine(""); 14 } 15 }
1 //繼承 父類的子類 (實現父類中的方法) 2 class ConcreteClassA:AbstractClass 3 { 4 public override void PrimitiveOperation1() 5 { 6 Console.WriteLine("具體的A類方法1實現"); 7 } 8 9 public override void PrimitiveOperation2() 10 { 11 Console.WriteLine("具體的A類方法2實現"); 12 } 13 } 14 15 //繼承父類的子類(實現父類中的方法) 16 class ConcreteClassB:AbstractClass 17 { 18 public override void PrimitiveOperation1() 19 { 20 Console.WriteLine("具體的B類方法1實現"); 21 } 22 23 public override void PrimitiveOperation2() 24 { 25 Console.WriteLine("具體的B類方法2實現"); 26 } 27 }
客戶端:
1 public static void Main() 2 { 3 AbstractClass c; 4 c = new ConcreteClassA(); 5 c.TemplageMethod(); 6 7 c = new ConcreteClassB(); 8 c.TemplageMethod(); 9 10 Console.Read(); 11 }
嗯,好了,以上就是模板方法模式。我們可以按照以上的模式,將案例改寫成模板方法模式了。小伙伴們可以自行的修改一下。
okok,好了,今天就講到了里了,下一篇博文我們會講 外觀模式
本系列將持續更新,喜歡的小伙伴可以點一下關註和推薦,謝謝大家的支持。