设计模式- 模板方法模式
我接触的设计模式不多,在我接触不多的设计模式里,我觉的单例模式和模板方法模式是最好理解的两种设计模式了。
我们先通过文字简单的理解一下什么是模板方法模式,然后用C#代码来写一个小例子加深一下了解,当然所谓的加深是相对初学者的加深。
先从字面上理解一下什么是模板方法设计模式,什么是模板?
1、我想很多人都懂甚至接触过,特别是对于大多数中学时考试成绩不理想的同学包括我,在那时候总是希望优秀的同学完成的作业借我们抄一下,然后我们只是在自己的作业本上改上自己的名字和简单的必要修改,那便可以交作业了,优秀同学已经写好的作业我们可以看作是模板,简单的必要修改和改名字这部份我们可以当作需要实现的虚类。
2、还有例如考英语试的时候,每个考生收到的试卷试题都是一样的,这张试卷可以理解成是模板。填上试卷的答案是有可能不同的,那么我们就不能将这部份归到模板上去。所以模板是共有的相同的一部份。
3、再随便的想一下,一台电脑一定会有显示器,键盘和主机,但不一定会有打印机,摄像头,无线网卡……。那么我们可以把显示器,键盘和主机这部份归划成一部份,这部份就是模板。而打印机,摄像头,无线网卡……这部份是不一定有的,所以不能划作模板。
用法
模板方法模式多用在:
- 某些类别的算法中,实做了相同的方法,造成程式码的重复。
- 控制子类别必须遵守的一些事项。
那么用程序应该怎么实现?
我们会把相同的一部份提取出来作为一个父类(这时父类就相同于一个模板),子类继承父类后就拥有了这个父类全部的内容,可以说这时子类抄了这个模板,但是模板上面不同的内容怎么改写,例如我总不能把借来同学抄的作业连他的名字也抄在自己的作业本上吧,那样老师一定一眼就看穿作业是抄来的。这时候可以通过在父类里用virtual或者abstract写一些方法,让子类继承父类后重写这些virtual或者abstract的方法后就拥有了不同的一部份了。那么也就是说可以写上自己的名子,作一些简单的修改了。。
我们来看一个例子,是《大话设计模式》书里的一个例子,关于考试试卷的,每个考生收到试卷的题目是不变的,所以可以作为模板,而答案是改变,那么这部份可以写成一个虚类(virtual)。看一下具体的代码实现。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 模板方法模式 { class Program { static void Main(string[] args) { Console.WriteLine("StudentA,s Paper:"); TestPaper studentA = new TestPaperA(); studentA.QuestionA(); studentA.QuestionB(); studentA.QuestionC(); Console.WriteLine("StudentA's Paper:"); TestPaper studentB = new TestPaperB(); studentB.QuestionA(); studentB.QuestionB(); studentB.QuestionC(); Console.Read(); } } public abstract class TestPaper { protected abstract string Answer1(); protected abstract string Answer2(); protected abstract string Answer3(); public void QuestionA() { Console.WriteLine("Question A"); Console.WriteLine("Answer:" + Answer1()); } public void QuestionB() { Console.WriteLine("Question B"); Console.WriteLine("Answer:" + Answer2()); } public void QuestionC() { Console.WriteLine("Question C"); Console.WriteLine("Answer:" + Answer3()); } } //学生A抄的试卷 class TestPaperA : TestPaper { protected override string Answer1() { return "b"; } protected override string Answer2() { return "c"; } protected override string Answer3() { return "a"; } } //学生B抄的试卷 class TestPaperB : TestPaper { protected override string Answer1() { return "c"; } protected override string Answer2() { return "a"; } protected override string Answer3() { return "a"; } } }