设计模式与实例代码:Template Method模式

来源:互联网 发布:云计算服务器搭建 编辑:程序博客网 时间:2024/06/05 22:20

意图/定义:定义一个操作算法的骨架,将一些步骤推迟到子类中实现。使得子类可以不改变算法的结构而重定义此算法的步骤

问题:要完成在某一细节层次一致的一个过程或一系列步骤,全其个别步骤在更详细的层次上实现可能不同

解决方案:允许定义可变的子步骤,同时保持基本过程一致

参与者与协作者:模板方法由一个抽象类组成,这个抽象类定义了需要覆盖的基本方法,每个从这个抽象类派生的具体类将为此模板实现新方法。

效果:模板提供了一个比较好的代码利用平台。它还有助于确保所需步骤的实现。它将每个具体类的覆盖步骤绑定起来,因此只有在这些变化总是并且只能一起发生时,才应用使用模板方法。

实现:创建一人抽象类,用抽象方法实现一个过程。这些抽象方法必须在子类中实现,以执行过程的每一个步骤。如果这些步骤是独立变化的,则每个步骤都可以用策略模式来实现。


下面是一个模板方法的示例,演示了两个访问数据库操作的两个具体类,两个类在基类中实现了共同的操作如打开连接、关闭连接,但在这个连接上具体选择哪个表及做什么处理是由基类实现的。

using System;using System.Data;using System.Data.OleDb;namespace Template{    /// <summary>    /// MainApp startup class for Real-World    /// Template Design Pattern.    /// </summary>    class MainApp    {        /// <summary>        /// Entry point into console application.        /// </summary>        static void Main()        {            DataAccessObject daoCategories = new Categories();            daoCategories.Run();            DataAccessObject daoProducts = new Products();            daoProducts.Run();            // Wait for user            Console.ReadKey();        }    }    /// <summary>    /// The 'AbstractClass' abstract class    /// </summary>    abstract class DataAccessObject    {        protected string connectionString;        protected DataSet dataSet;        public virtual void Connect()        {            // Make sure mdb is available to app            connectionString =              "provider=Microsoft.JET.OLEDB.4.0; " +              "data source=..\\..\\..\\db1.mdb";        }        public abstract void Select();        public abstract void Process();        public virtual void Disconnect()        {            connectionString = "";        }        // The 'Template Method'        public void Run()        {            Connect();            Select();            Process();            Disconnect();        }    }    /// <summary>    /// A 'ConcreteClass' class    /// </summary>    class Categories : DataAccessObject    {        public override void Select()        {            string sql = "select CategoryName from Categories";            OleDbDataAdapter dataAdapter = new OleDbDataAdapter(sql, connectionString);            dataSet = new DataSet();            dataAdapter.Fill(dataSet, "Categories");        }        public override void Process()        {            Console.WriteLine("Categories ---- ");            DataTable dataTable = dataSet.Tables["Categories"];            foreach (DataRow row in dataTable.Rows)            {                Console.WriteLine(row["CategoryName"]);            }            Console.WriteLine();        }    }    /// <summary>    /// A 'ConcreteClass' class    /// </summary>    class Products : DataAccessObject    {        public override void Select()        {            string sql = "select ProductName from Products";            OleDbDataAdapter dataAdapter = new OleDbDataAdapter(              sql, connectionString);            dataSet = new DataSet();            dataAdapter.Fill(dataSet, "Products");        }        public override void Process()        {            Console.WriteLine("Products ---- ");            DataTable dataTable = dataSet.Tables["Products"];            foreach (DataRow row in dataTable.Rows)            {                Console.WriteLine(row["ProductName"]);            }            Console.WriteLine();        }    }}