模板方法模式定義演算法骨架,將特定步驟延遲至子類別實作。子類別可在不改變演算法結構下重新定義步驟。將不變行為上移至超類別,消除重複代碼,提供代碼復用平台。
完成一致性流程,但個別步驟在詳細層面實作不同時。
TemplateMethod() 定義演算法框架,宣告抽象 PrimitiveOperation1/2()
public abstract class AbstractClass {
public abstract void PrimitiveOperation1();
public abstract void PrimitiveOperation2();
public void TemplateMethod() {
PrimitiveOperation1(); PrimitiveOperation2(); Console.WriteLine("模板方法執行完");
}
}
public class ConcreteClassA : AbstractClass {
public override void PrimitiveOperation1() => Console.WriteLine($"具體實現類{GetType().Name}方法1實現");
public override void PrimitiveOperation2() => Console.WriteLine($"具體實現類{GetType().Name}方法2實現");
}
public class ConcreteClassB : AbstractClass {
public override void PrimitiveOperation1() => Console.WriteLine($"具體實現類{GetType().Name}方法1實現");
public override void PrimitiveOperation2() => Console.WriteLine($"具體實現類{GetType().Name}方法2實現");
}
// Client
static void Main() {
AbstractClass ac = new ConcreteClassA(); ac.TemplateMethod();
ac = new ConcreteClassB(); ac.TemplateMethod();
}
定義資料操作骨架:Connect → Select → Process → Disconnect。Connect/Disconnect 通用放基類,Select/Process 交由子類實作。
abstract class DataAccessObject {
protected string connectionString; protected DataSet dataSet;
public virtual void Connect() => connectionString = "provider=Microsoft.JET.OLEDB.4.0;data source=..\\..\\..\\db1.mdb";
public abstract void Select(); public abstract void Process();
public virtual void Disconnect() => connectionString = "";
public void Run() { Connect(); Select(); Process(); Disconnect(); }
}
class Categories : DataAccessObject {
public override void Select() {
string sql = "select CategoryName from Categories";
var da = new OleDbDataAdapter(sql, connectionString);
dataSet = new DataSet(); da.Fill(dataSet, "Categories");
}
public override void Process() {
Console.WriteLine("Categories ----");
foreach (DataRow row in dataSet.Tables["Categories"].Rows) Console.WriteLine(row["CategoryName"]);
Console.WriteLine();
}
}
class Products : DataAccessObject {
public override void Select() {
string sql = "select ProductName from Products";
var da = new OleDbDataAdapter(sql, connectionString);
dataSet = new DataSet(); da.Fill(dataSet, "Products");
}
public override void Process() {
Console.WriteLine("Products ----");
foreach (DataRow row in dataSet.Tables["Products"].Rows) Console.WriteLine(row["ProductName"]);
Console.WriteLine();
}
}
// Client
static void Main() {
new Categories().Run(); new Products().Run();
}
模板方法模式是框架設計核心模式,透過「好萊塢原則」(Don't call us, we'll call you)實現控制反轉,廣泛應用於資料存取、演算法框架、流程引擎等領域。