模板方法模式(Template Method Pattern)
模版方法中的方法可以分为两大类:模版方法(Template Method)和基本方法(Primitive Method)。
a.模版方法
一个模版方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。
这个模版方法一般会在抽象类中定义,并由子类不加以修改地完全继承下来。
b.基本方法
基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和
钩子方法(Hook Method)。
抽象方法:一个抽象方法由抽象类声明,由具体子类实现。在C#语言里一个抽象方法以abstract
关键字标示出来。
具体方法:一个具体方法由抽象类声明并实现,而子类并不实现或置换。在C#语言里面,一个具体方法
没有abstract关键字。
钩子方法:一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,
作为方法的默认实现。(Visual FoxPro中项目向导建立的项目会使用一个AppHook类实现监视项目成员变化,调整系统结构的工作。)钩子方法的名字通常以do开始。
下面讲解窗体基类的模板方法实现:
抽象方法必须定义在抽象类中(Abstract Class),在某些场合不一定使用抽象类,比如frmBase是个具体类,因此我将模板方法改为虚拟(Virtual)的。
/// <summary>
/// 在基类定义查询数据的模板方法,由派生窗体实现具体的查询功能。
/// </summary>
/// <returns></returns>
protected virtual DataTable DoSearch()
{
return new DataTable(); //模板方法不能返回实际数据。
}
派生类具体实现:
//复写(Override)模板方法,具体实现
protected override DataTable DoSearch()
{
return new BLL_Product().Search(txtProductCode.Text, txtProductName.Text);
}
窗体基类界面:
{
public frmBase()
{
InitializeComponent();
}
private void btnSearch_Click(object sender, EventArgs e)
{
//调用模板方法
DataTable data = this.DoSearch();
if (data.Rows.Count > 0)
this.dataGridView1.DataSource = data;
else
MessageBox.Show("没有找到数据!");
}
/// <summary>
/// 在基类定义查询数据的模板方法,由派生窗体实现具体的查询功能。
/// </summary>
/// <returns></returns>
protected virtual DataTable DoSearch()
{
return new DataTable(); //模板方法不能返回实际数据。
}
}
派生一个产品定义窗体:
{
public frmProduct()
{
InitializeComponent();
}
//复写(Override)模块方法,具体实现
protected override DataTable DoSearch()
{
return new BLL_Product().Search(txtProductCode.Text, txtProductName.Text);
}
}
搜索功能在窗体基类实现了,我们只需要定义具体的数据查找方法。
通过重写DoSearch模块方法,从业务逻辑层返回数据。
/// <summary>
/// 业务逻辑层
/// </summary>
public class BLL_Product
{
public DataTable Search(string productCode, string productName)
{
string where = " 1=1 ";
if (!String.IsNullOrEmpty(productCode))
where = where + " and ProductCode=’" + productCode + "’";
if (!String.IsNullOrEmpty(productName)) //支持模糊查找
where = where + " and ProductName like ’%" + productName + "%’";
string sql = "select * from tb_Product where " + where;
//从SQL Server 获取数据 ..........省略...........
//
//下面返回测试数据
DataTable test = this.GetDemoData();//返回测试数据
DataRow[] rows = test.Select(where);
//克隆 System.Data.DataTable 的结构,包括所有 System.Data.DataTable 架构和约束。
DataTable retTable = test.Clone();
foreach (DataRow row in rows)
retTable.ImportRow(row);
return retTable;
}
/// <summary>
/// 构建测试数据表
/// </summary>
/// <returns></returns>
private DataTable GetDemoData()
{
DataTable dt = new DataTable();
dt.Columns.Add("ProductCode", typeof(String));
dt.Columns.Add("ProductName", typeof(String));
dt.Columns.Add("Price", typeof(Decimal));
dt.Rows.Add("001", "原创作品CD", 99);
dt.Rows.Add("002", "Dev Express 9.2x Suit", 9960);
dt.Rows.Add("003", "可口可乐", 1.90);
dt.Rows.Add("004", "Engima CD", 269);
return dt;
}
}