今天我们来讲一下模板方法模式。
一、案例
我们在上中学的时候,会有这么一种场景,老师在黑板上写测试题,让我们自己抄到纸上做。相信不少小伙伴们都经历过这种岁月,想想还是很怀念的呢。这种做测试的方式,对当时的我们来讲,有一个最致命的痛苦,就是这个题目会做,但是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,好了,今天就讲到了里了,下一篇博文我们会讲 外观模式
本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持。
原文:http://www.cnblogs.com/xiaomowang/p/6293560.html