zoukankan      html  css  js  c++  java
  • 模板方法模式(9)

    今天我们来讲一下模板方法模式。

    一、案例

    我们在上中学的时候,会有这么一种场景,老师在黑板上写测试题,让我们自己抄到纸上做。相信不少小伙伴们都经历过这种岁月,想想还是很怀念的呢。这种做测试的方式,对当时的我们来讲,有一个最致命的痛苦,就是这个题目会做,但是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,好了,今天就讲到了里了,下一篇博文我们会讲 外观模式


    本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持。

  • 相关阅读:
    51nod 1412 AVL树的种类
    bzoj1093 [ZJOI2007]最大半联通子图 缩点 + 拓扑序
    bzoj1116 [POI2008]CLO 边双联通分量
    luoguP4366 [Code+#4]最短路 最短路
    51nod1821 最优集合 贪心
    51nod2000 四边形分割平面 规律题
    luoguP3250 [HNOI2016]网络 树链剖分 + 堆
    [Luogu5162]WD与积木(多项式求逆)
    [Luogu5161]WD与数列(后缀数组/后缀自动机+线段树合并)
    [Luogu5106]dkw的lcm
  • 原文地址:https://www.cnblogs.com/xiaomowang/p/6293560.html
Copyright © 2011-2022 走看看