Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9637232
  • 博文数量: 1293
  • 博客积分: 13501
  • 博客等级: 上将
  • 技术积分: 17974
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-08 18:11
文章分类

全部博文(1293)

文章存档

2019年(1)

2018年(1)

2016年(118)

2015年(257)

2014年(128)

2013年(222)

2012年(229)

2011年(337)

分类: 架构设计与优化

2013-01-26 15:22:21

1、现象分析

全国各个大、中、小学都有早上让学生出操的习惯。常常有部分同学不愿意出动,经常缺席早操早锻炼。因此,教务处每天都要实施早操点名汇报制度。

一个学校往往有多个年级、年级里有多个班。当各班班长清点完人数后,向领导汇报人数时的格式基本一样,即:

XXX班有多少人,实到多少人,未到多少人,XXX班长YYY,报到完毕!

 

2、模板方法模式在学生出操点名的应用

可以考虑利用模板方法,将其实现。

UML图如下:

 

image 图1 基本结构图


如图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); 
           } 
       } 
   }

运行效果如下:

image

图2 出操情况汇报

在main()函数中调用时,我们只是重复使用了下面的语句

CClassInfo classInfo = new CGrade1ClassInfo(1, 80, 78);

classInfo.ReportRegistInfoTemplate();


根据不同的对象,创建不同的实例,再通过大家统一的模板方法接口:

            public void ReportRegistInfoTemplate()
           {
               Console.WriteLine(" {0}年级 {1}班:总人数{2}人,实到人数{3}人,{4}人未到。",
                                           GetGradeNum(),this.CassNo,this.TotalStuNumber,this.ActualPreset,
                                           (this.TotalStuNumber-this.ActualPreset));
               this.ShowReporterName();
           }

从而避免了大量重复(相似)的方法在派生类中多次实现的问题。

 

上面案例印证了下面的观点:

模板方法模式通过把不变行为搬移到超类,去除子类中的重复代码。


案例源码

StudentCheckInSystem.zip

阅读(2057) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~