模板方法模式(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,好了,今天就讲到了里了,下一篇博文我们会讲 外观模式


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

原文地址:https://www.cnblogs.com/xiaomowang/p/6293560.html