模板方法模式
继承:
作为面向对象三大特性之中的一个的继承,功能不是一般的强大,在书的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()方法还是子类所共同拥有的。
我们已经知道反复的危害。easy出错,并且在改动的时候非常困难。所以以下我们要做的就是提炼代码。将同样的代码提到一个共同拥有的父类中。
优化后
代码结构图
父类
<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>乙类代码和甲类同样仅仅是在输出答案的时候不同。
client代码:
<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>
模板方法模式通过把不变的行为搬移到超类中去除了子类中的反复代码,提供了一个非常好的代码复用平台。
总结:模板模式充分体现了继承的优点。通过提取不变的行为抽象为父类,从而简化的代码的反复,优化了系统的结构。是我们非经常常使用的模式。