標籤:style blog http strong 2014 io
繼承:
作為物件導向三大特性之一的繼承,功能不是一般的強大,在書的344頁《大話設計模式》我們可以看到Cat和Dog類代碼內容基本形同,只是在叫的時候發出的聲音不同罷了,如果現在我們要添加別的動物,比如兔子,豬...等等,則需要寫相同的代碼(複製)只是改改各自的叫聲罷了。
我們知道一條編程的原則就是儘可能的避免重複,比較四個類,可以抽象出animal這個類作為父類把相同的代碼放在父類中,然後子類通過多態實現對叫聲Shout()方法的重寫實現各自的叫聲。
繼承的好處:子類擁有父類非private的屬性和功能;子類是父類的特殊化;子類可以對父類的方法進行重寫。
模板方法模式:
定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變一個演算法的結構即了重新定義該演算法的某些特定步驟。
說白了就是幾個類的主要代碼基本相同,只是個別步驟的演算法不同。我們用模板模式對代碼進行重構。
以老師在黑板上抄題,學生抄寫題目並寫出相應的答案為例。
代碼結構圖
//學生甲的試卷ClassTestPaperA{ //試題1 public void TestQuestion1() { Console.WriteLine("2+1=[ ] a.0 b.1 c.2 d.3") Console.WriteLine("答案:c") } //試題2 public vodi TestQuestion2() { Console.WriteLine("2-1= [] a.0 b.1 c.2 d.3") Console.WriteLine("答案:c") } //試題3 public vodi TestQuestion3() { Console.WriteLine("2*1= [] a.0 b.1 c.2 d.3") Console.WriteLine("答案:c") } }
//學生乙的試卷ClassTestPaperA{ //試題1 public void TestQuestion1() { Console.WriteLine("2+1=[ ] a.0 b.1 c.2 d.3") Console.WriteLine("答案:d") } //試題2 public vodi TestQuestion2() { Console.WriteLine("2-1= [] a.0 b.1 c.2 d.3") Console.WriteLine("答案:d") } //試題3 public vodi TestQuestion3() { Console.WriteLine("2-1= [] a.0 b.1 c.2 d.3") Console.WriteLine("答案:d") } }
比較甲乙抄寫試卷的代碼我們知道,試卷中的試題是相同的不同的只是甲乙各自的答案Console.WriteLine("")不同。確切的說是輸出的答案(a.b.c.d)不同,而Console.WriteLine()方法還是子類所共有的。
我們已經知道重複的危害,容易出錯,而且在修改的時候很困難。所以下面我們要做的就是提煉代碼,將相同的代碼提到一個共有的父類中。
最佳化後
代碼結構圖
父類
<span style="font-size:14px;">class TestPaper{ //試題1 public void TestQuestion1() { Console.WriteLine("2+1=[ ] a.0 b.1 c.2 d.3") Console.WriteLine("答案:+ Answer1()") /Answer1()是個虛方法, } protected virtual stringAnswer1() /讓子類重寫該方法 { return "" }} //試題2 public vodi TestQuestion2() { Console.WriteLine("2-1= [] a.0 b.1 c.2 d.3") Console.WriteLine("答案:+ Answer2()") } protected virtual string Answer2() { return "" } //試題3 public vodi TestQuestion3() { Console.WriteLine("2*1= [] a.0 b.1 c.2 d.3") Console.WriteLine("答案:+ Answer3()") } protected virtual string Answer() { return "" }</span>
子類的代碼
<span style="font-size:14px;">//甲類classTestPaperA : TestPaper{ protected override string Answer1 { return c; } protected override string Answer2 { return c; } protected override string Answer3 { return c; } }</span>乙類代碼和甲類相同只是在輸出答案的時候不同。
用戶端代碼:
<span style="font-size:14px;">static void Main(string[] args){ Console.WriteLine("學生甲抄的試卷:"); TestPaper studentA = new TestPaperA(); studentA.TestQusetion1(); studentA.TestQusetion2(); studentA.TestQusetion3(); Console.WriteLine("學生乙抄的試卷:"); TestPaper studentB = new TestPaperA(); studentB.TestQusetion1(); studentB.TestQusetion2(); studentB.TestQusetion3();}</span>
模板方法模式通過把不變的行為搬移到超類中去除了子類中的重複代碼,提供了一個很好的代碼複用平台。
總結:模板模式充分體現了繼承的好處,通過提取不變的行為抽象為父類,從而簡化的代碼的重複,最佳化了系統的結構,是我們很常用的模式。