版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xml1996/article/details/84176114
什么是模板方法:
模板方法模式,定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可冲定义该算法的某些特定步骤。
有趣易懂的解释:
推荐博客:作者:Carson_Ho ,原文:模板方法易懂解析
- 背景:小成希望学炒菜:手撕包菜 & 蒜蓉炒菜心
- 冲突:两道菜的炒菜步骤有的重复有的却差异很大,记不住
- 解决方案:利用代码记录下来
步骤1: 创建抽象模板结构(Abstract Class):炒菜的步骤
public abstract class Abstract Class {
//模板方法,用来控制炒菜的流程 (炒菜的流程是一样的-复用)
//申明为final,不希望子类覆盖这个方法,防止更改流程的执行顺序
final void cookProcess(){
//第一步:倒油
this.pourOil();
//第二步:热油
this.HeatOil();
//第三步:倒蔬菜
this.pourVegetable();
//第四步:倒调味料
this.pourSauce();
//第五步:翻炒
this.fry();
}
//定义结构里哪些方法是所有过程都是一样的可复用的,哪些是需要子类进行实现的
//第一步:倒油是一样的,所以直接实现
void pourOil(){
System.out.println("倒油");
}
//第二步:热油是一样的,所以直接实现
void HeatOil(){
System.out.println("热油");
}
//第三步:倒蔬菜是不一样的(一个下包菜,一个是下菜心)
//所以声明为抽象方法,具体由子类实现
abstract void pourVegetable();
//第四步:倒调味料是不一样的(一个下辣椒,一个是下蒜蓉)
//所以声明为抽象方法,具体由子类实现
abstract void pourSauce();
//第五步:翻炒是一样的,所以直接实现
void fry();{
System.out.println("炒啊炒啊炒到熟啊");
}
}
步骤2: 创建具体模板(Concrete Class),即”手撕包菜“和”蒜蓉炒菜心“的具体步骤
//炒手撕包菜的类
public class ConcreteClass_BaoCai extend Abstract Class{
@Override
public void pourVegetable(){
System.out.println(”下锅的蔬菜是包菜“);
}
@Override
public void pourSauce(){
System.out.println(”下锅的酱料是辣椒“);
}
}
//炒蒜蓉菜心的类
public class ConcreteClass_CaiXin extend Abstract Class{
@Override
public void pourVegetable(){
System.out.println(”下锅的蔬菜是菜心“);
}
@Override
public void pourSauce(){
System.out.println(”下锅的酱料是蒜蓉“);
}
}
步骤3: 客户端调用-炒菜了
public class Template Method{
public static void main(String[] args){
//炒 - 手撕包菜
ConcreteClass_BaoCai BaoCai = new ConcreteClass_BaoCai();
BaoCai.cookProcess();
//炒 - 蒜蓉菜心
ConcreteClass_ CaiXin = new ConcreteClass_CaiXin();
CaiXin.cookProcess();
}
}
组合查询如何体现模板方法
组合查询在很多地方都可以用:如学生信息查询;学生上下机记录查询;学生充值信息查询;教师上机记录查询等。
组合查询窗体的建立和初始化的内容都比较多,那就把他们共同的点抽象出来,封装成一个类,让如上这些子类继承它。
例如:
第一点:父类的组合窗体抽象出来的方法:
第二点:重点看父类中的虚方法
模板方法体现在分类中的虚方法命名,在子类中实现重写
//将查询的内容转换成数据库中的列名称
public virtual string ToName(string combo)
{
return "";
}
//获得数据库名称:在子窗体中进行重写,返回需要查询的表名
protected virtual string Getdbtable()
{
return "";
}
//显示数据:在子窗体中实现传值,返回表显示出来
protected virtual void ToDgv(enGroupFind enGroupFind)
{
}
第三点:重点看子类中的虚方法重写
/// <summary>
/// 重写虚方法:将查询的内容转换成数据库中的列名称
/// </summary>
/// <param name="combo"></param>
/// <returns></returns>
public override string ToName(string combo)
{
switch (combo)
{
case "卡号":
return "userID";
case "学号":
return "studentID";
case "注册日期":
return "date";
case "与":
return "and";
case "或":
return "or";
case "非":
return "not";
//如果用到了ToName方法但是没有输入值则返回空
default:
return "";
}
}
/// <summary>
/// 重写虚方法:获得数据库名称
/// </summary>
/// <returns></returns>
protected override string Getdbtable()
{
return "student_info";
}
/// <summary>
/// 重写虚方法:显示数据
/// </summary>
/// <param name="enGroupFind"></param>
protected override void ToDgv(enGroupFind enGroupFind)
{
//传值到外观层
Facade.enGroupFindFacade grouFind = new Facade.enGroupFindFacade();
DataTable result = new DataTable();
result = grouFind.GroupCheck(enGroupFind);
if (result .Rows.Count == 0)
{
MessageBox.Show("没有记录");
}
else
{
//把查询到的tabe result 返回到表中
dgvCollect.DataSource = result;
dgvCollect.Refresh();
}
}
具体详细代码部分见:组合查询详细代码
理解还不到位,请各位指正赐教