一 、  一个实际应用模板方法的例子 
 
下面的例子演示了数据库访问的模板方法。实际应用时,请确保 C 盘根目录下有 nwind.mdb 这个 Access 数 
据库(可以从 Office 的安装目录下找到。中文版用户的请注意字段名可能有所不同)。 
 
[C#] 纯文本查看 复制代码 using System;
using System.Data;
using System.Data.OleDb;
namespace ConsoleApplication1
{
    // "AbstractClass"
    abstract class DataObject
    {
        // Methods
        public abstract void Connect();
        public abstract void Select();
        public abstract void Process();
        public abstract void Disconnect();
        // The "Template Method"
        public void Run()
        {
            Connect();
            Select();
            Process();
            Disconnect();
        }
    }
    // "ConcreteClass"
    class CustomerDataObject : DataObject
    {
        private string connectionString =
            "provider=Microsoft.JET.OLEDB.4.0; "
            + "data source=c:\\nwind.mdb";
        private string _commandString;
        private DataSet _dataSet;
        // Methods
        public override void Connect()
        {
            // Nothing to do
        }
        public override void Select()
        {
            _commandString = "select CompanyName from Customers";
            OleDbDataAdapter dataAdapter = new OleDbDataAdapter(
                _commandString, connectionString);
            _dataSet = new DataSet();
            dataAdapter.Fill(_dataSet, "Customers");
        }
        public override void Process()
        {
            DataTable dataTable = _dataSet.Tables["Customers"];
            foreach (DataRow dataRow in dataTable.Rows)
                Console.WriteLine(dataRow["CompanyName"]);
        }
        public override void Disconnect()
        {
            // Nothing to do
        }
    }
    /// <summary>
    /// TemplateMethodApp test
    /// </summary>
    public class TemplateMethodApp
    {
        public static void Main(string[] args)
        {
            CustomerDataObject c = new CustomerDataObject();
            c.Run();
        }
    }
} 
 
二 、  模版方法模式中的方法 
 
模版方法中的方法可以分为两大类:模版方法(Template Method)和基本方法(Primitive Method)。 
 
模版方法 
 
一个模版方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。这个模版 
方法一般会在抽象类中定义,并由子类不加以修改地完全继承下来。 
 
基本方法 
 
基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(HookMethod)。 
抽象方法:一个抽象方法由抽象类声明,由具体子类实现。在 C#语言里一个抽象方法以 abstract 关键字标示出来。 
 
具体方法:一个具体方法由抽象类声明并实现,而子类并不实现或置换。在 C#语言里面,一个具体方法没有 
abstract 关键字。 
 
钩子方法:一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,作为 
方法的默认实现。(Visual FoxPro 中项目向导建立的项目会使用一个 AppHook 类实现监视项目成员变化,调 
整系统结构的工作。)钩子方法的名字通常以 do 开始。 
 
 
三 、  重构的原则 
 
在对一个继承的等级结构做重构时,一个应当遵从的原则便是将行为尽量移动到结构的高端,而将状态尽量移动 
到结构的低端。 
 
1995 年,Auer 曾在文献【AUER95】中指出: 
 
1. 应当根据行为而不是状态定义一个类。也就是说,一个类的实现首先建立在行为的基础之上,而不是建立在状态的基础之上。 
 
2. 在实现行为时,是用抽象状态而不是用具体状态。如果一个行为涉及到对象的状态时,使用间接的引用而不是直接的引用。换言之,应当使用取值 
方法而不是直接引用属性。 
 
3. 给操作划分层次。一个类的行为应当放到一个小组核心方法(KernelMethods)里面,这些方法可以很方便地在子类中加以置换。 
 
4. 将状态属性的确认推迟到子类中。不要在抽象类中过早地声明属性变量,应将它们尽量地推迟到子类中去声明。在抽象超类中,如果需要状态属性 
的话,可以调用抽象的取值方法,而将抽象的取值方法的实现放到具体子类中。 
 
如果能够遵从这样的原则,那么就可以在等级结构中将接口与实现分隔开来,将抽象与具体分割开来,从而保证 
代码可以最大限度地被复用。这个过程实际上是将设计师引导到模版方法模式上去。 |