1,无处不在的Template Method 模式
需求的变化是软件设计永恒的定理,如何管理变化带来的复杂性呢?,设计模式的艺术性和复杂度就在于如何分析,和发现分析系统中的变化点和稳定点
Template Method模式的意图就是定义一种稳定不变的算法结构,然后变化的部分在子类中去实现。就像我们查询数据库一样,我们不管是查询那一张表,他都将是下面的步骤:
1.连接数据库(Connect)
2.执行查询命令(Select)
3.显示数据(Display)
4.断开数据库连接(Disconnect)
这些步骤是固定的,但是对于每一张具体的数据表所执行的查询却是不一样的。显然这需要一个抽象角色,给出顶级行为的实现。
Template Method模式的实现方法是从上到下,我们首先给出顶级框架DataAccessObject的实现逻辑:
using System;
using System.Data;
using System.Data.SqlClient;
public class DataAccessObject
{
protected string conectionString;
protected DataSet DataSet;
protected virtual void Connect()
{
conectionString = "Server =.;User Id =sa;Password=;database = Northod";
}
protected abstract void Select();
protected abstract void Display();
protected virtual void Disconnect()
{
conectionString = "";
}
public void Run()
{
Connect ();
Select ();
Display ();
Disconnect ();
}
}
class Categories : DataAccessObject
{
protected override void Select()
{
string sql = "select CategoryName from Categories";
SqlDataAdapter dataAdapter = new SqlDataAdapter(
sql, conectionString);
DataSet = new DataSet();
dataAdapter.Fill(DataSet, "Categories");
}
protected override void Display()
{
Console.WriteLine("Categories ---- ");
DataTable dataTable = DataSet.Tables["Categories"];
foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine(row["CategoryName"].ToString());
}
}
}
class Products : DataAccessObject
{
protected override void Select()
{
string sql = "select top 10 ProductName from Products";
SqlDataAdapter dataAdapter = new SqlDataAdapter(
sql, conectionString);
DataSet = new DataSet();
dataAdapter.Fill(DataSet, "Products");
}
protected override void Display()
{
Console.WriteLine("Products ---- ");
DataTable dataTable = DataSet.Tables["Products"];
foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine(row["ProductName"].ToString());
}
Console.WriteLine();
}
}
class TemplateMethondTest
{
public void Mian()
{
DataAccessObject dao;
dao = new Categories();
dao.Run();
dao = new Products();
dao.Run();
}
}
在上面的例子中,需要注意的是:
1.对于Connect()和Disconnect()方法实现为了virtual,而Select()和Display()方法则为abstract,这是因为如果这个方法有默认的实现,则实现为virtual,否则为abstract。
2.Run()方法作为一个模版方法,它的一个重要特征是:在基类里定义,而且不能够被派生类更改。有时候它是私有方法(private method),但实际上它经常被声明为protected。它通过调用其它的基类方法(覆写过的)来工作,但它经常是作为初始化过程的一部分被调用的,这样就没必要让客户端程序员能够直接调用它了。
3 .在一开始我们提到了不管读的是哪张数据表,它们都有共同的操作步骤,即共同点。因此可以说Template Method模式的一个特征就是剥离共同点。Template Mehtod实现要点:
1.Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性)为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。
2.除了可以灵活应对子步骤的变化外,“不用调用我,让我来调用你(Don't call me ,let me call you)”的反向控制结构是Template Method的典型应用。“Don’t call me.Let me call you”是指一个父类调用一个子类的操作,而不是相反。
3 .在具体实现方面,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法,纯虚方法),但一般推荐将它们设置为protected方法。