全部博文(1293)
分类: 架构设计与优化
2013-01-26 15:22:21
1、现象分析
全国各个大、中、小学都有早上让学生出操的习惯。常常有部分同学不愿意出动,经常缺席早操早锻炼。因此,教务处每天都要实施早操点名汇报制度。
一个学校往往有多个年级、年级里有多个班。当各班班长清点完人数后,向领导汇报人数时的格式基本一样,即:
XXX班有多少人,实到多少人,未到多少人,XXX班长YYY,报到完毕!
2、模板方法模式在学生出操点名的应用
可以考虑利用模板方法,将其实现。
UML图如下:
如图1,基类CClassInfo中定义了三个方法:
ReportRegistInfoTemplate()是一个模式方法,用来调用所定义的虚方法;
GetGradeNum()和ShowReporterName()是两个虚方法,必须由派生类进行实现。
案例代码如下:
class Program { static void Main(string[] args) { Console.WriteLine("各年级、各班开始汇报出操人数:\\n"); CClassInfo classInfo = new CGrade1ClassInfo(1, 80, 78); classInfo.ReportRegistInfoTemplate(); classInfo = new CGrade1ClassInfo(2, 82, 77); classInfo.ReportRegistInfoTemplate(); classInfo = new CGrade2ClassInfo(1, 86, 75); classInfo.ReportRegistInfoTemplate(); classInfo = new CGrade2ClassInfo(2, 90, 85); classInfo.ReportRegistInfoTemplate(); classInfo = new CGrade3ClassInfo(1, 100, 95); classInfo.ReportRegistInfoTemplate(); classInfo = new CGrade3ClassInfo(2, 88, 82); classInfo.ReportRegistInfoTemplate(); Console.ReadLine(); } public class CClassInfo { public int CassNo; public int TotalStuNumber; public int ActualPreset; public CClassInfo(int classNo, int totalStuNumber, int actualPresent) { CassNo = classNo; TotalStuNumber = totalStuNumber; ActualPreset = actualPresent; } // 模板方法里面也两个虚方法进行调用 public void ReportRegistInfoTemplate() { Console.WriteLine(" {0}年级 {1}班:总人数{2}人,实到人数{3}人,{4}人未到。", GetGradeNum(),this.CassNo,this.TotalStuNumber,this.ActualPreset, (this.TotalStuNumber-this.ActualPreset)); this.ShowReporterName(); } /* 定义一个虚方法留在子类实现 */ public virtual string GetGradeNum() { return ""; } public virtual void ShowReporterName() { Console.WriteLine(""); } } ////// 具体的模板角色 /// 实现所定义的一个或多个虚(或抽象)方法。 /// 每一个模板方法可以任意个实现 /// public class CGrade1ClassInfo : CClassInfo { int gradeNo = 1; public CGrade1ClassInfo(int classNo, int totalStuNumber, int actualPresent) : base(classNo,totalStuNumber,actualPresent) { } public override string GetGradeNum() { return gradeNo.ToString(); } public override void ShowReporterName() { Console.WriteLine(" 一年级{0}班长Kobe{1},报告完毕!\\n", base.CassNo,base.CassNo); } } public class CGrade2ClassInfo : CClassInfo { int gradeNo =2; public CGrade2ClassInfo(int classNo, int totalStuNumber, int actualPresent) : base(classNo,totalStuNumber,actualPresent) { } public override string GetGradeNum() { return gradeNo.ToString(); } public override void ShowReporterName() { Console.WriteLine(" 二年级{0}班长James{1},报告完毕!\\n", base.CassNo, base.CassNo); } } public class CGrade3ClassInfo : CClassInfo { int gradeNo = 3; public CGrade3ClassInfo(int classNo, int totalStuNumber, int actualPresent) : base(classNo,totalStuNumber,actualPresent) { } public override string GetGradeNum() { return gradeNo.ToString(); } public override void ShowReporterName() { Console.WriteLine(" 三年级{0}班长Durant{1},报告完毕!\\n", base.CassNo, base.CassNo); } } }
运行效果如下:
图2 出操情况汇报
在main()函数中调用时,我们只是重复使用了下面的语句
CClassInfo classInfo = new CGrade1ClassInfo(1, 80, 78);classInfo.ReportRegistInfoTemplate();
根据不同的对象,创建不同的实例,再通过大家统一的模板方法接口:
public void ReportRegistInfoTemplate()从而避免了大量重复(相似)的方法在派生类中多次实现的问题。
上面案例印证了下面的观点:
模板方法模式通过把不变行为搬移到超类,去除子类中的重复代码。
案例源码