首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 設計模式實戰:模板方法模式打造可擴展演算法骨架

     編輯:關於C#

前言

在開發過程中,我們常遇到一類問題:演算法的整體流程固定,但某些步驟的具體實作因子系統而異。例如「先驗證權限,再查詢資料」,驗證邏輯固定,查詢來源可能是 SQL Server、XML 或 API。若在每個子類別重複整個流程,違反 DRY 原則;若將流程寫在基類別,又難以客製化步驟。模板方法模式正是為了解決此類問題而生:在基類別定義演算法骨架,將易變步驟延遲至子類別實作。

模式結構與角色

本範例以訊息查詢為例,展示「先驗證用戶,再取得資料」的固定流程:

  • AbstractClass(抽象類別):AbstractMessageTemplate,定義模板方法 TemplateMethodGet() 及基本步驟 ValidateUser()(可覆寫)、Get()(抽象,強制子類別實作)。
  • ConcreteClass(具體類別):SqlMessage、XmlMessage,實作 Get() 提供不同資料來源查詢邏輯。
模板方法模式類別圖

核心程式碼深度解析

1. 抽象類別:定義演算法骨架

AbstractMessageTemplate 封裝不變的流程:

public List<MessageModel> TemplateMethodGet()
{
    if (ValidateUser())
    {
        return Get(); // 延遲至子類別
    }
    else
    {
        List<MessageModel> l = new List<MessageModel>();
        l.Add(new MessageModel("無權獲取", DateTime.Now));
        return l;
    }
}

// 可被子類別覆寫的鉤子方法
public virtual bool ValidateUser()
{
    return this._userId == "admin";
}

public abstract List<MessageModel> Get(); // 必須實作

關鍵設計點:

  • TemplateMethodGet() 為 final(C# 中非 virtual 即不可覆寫),保護演算法結構不被破壞。
  • ValidateUser() 宣告為 virtual,提供預設實作,子類別可選擇性覆寫(Hook 方法)。
  • Get() 為 abstract,強制子類別實作核心差異邏輯。

2. 具體類別:實作差異步驟

SqlMessage 與 XmlMessage 僅需實作 Get():

public override List<MessageModel> Get()
{
    List<MessageModel> l = new List<MessageModel>();
    l.Add(new MessageModel("SQL方式獲取Message", DateTime.Now));
    return l;
}

構造函數透過 base(userId) 傳遞用戶識別碼給基類別,確保驗證邏輯可用。

3. 客戶端使用展示

AbstractMessageTemplate m = new XmlMessage("user"); // 非 admin
Response.Write(m.TemplateMethodGet()[0].Message); // 輸出:無權獲取

m = new SqlMessage("admin"); // admin
Response.Write(m.TemplateMethodGet()[0].Message); // 輸出:SQL方式獲取Message

執行結果分析

無權獲取 2007-3-13 22:29:55
SQL方式獲取Message 2007-3-13 22:29:55

結果驗證:相同流程(驗證→查詢),不同用戶權限與資料來源產生不同結果,且核心流程程式碼零重複。

進階應用:鉤子方法與好萊塢原則

模板方法模式體現「好萊塢原則」——「別呼叫我們,我們會呼叫你」。基類別掌控流程,子類別只在特定點被「回呼」。進階技巧包含:

  • 鉤子方法:如 ValidateUser() 提供預設行為,子類別可選擇覆寫或保留。
  • 強制實作 vs 可選實作:abstract 強制實作核心步驟;virtual 提供預設實作作為可選擴展點。
  • 防止惡意覆寫:模板方法標記為 sealed(或非 virtual),確保演算法骨架不被子類別竄改。

優缺點與適用場景

優點

  • 程式碼複用:將共同流程集中在基類別,避免重複。
  • 反轉控制:基類別呼叫子類別操作,符合依賴倒置原則。
  • 結構穩定:演算法骨架固定,易於維護與理解。

缺點

  • 類別數量增加:每個不同實作都需一個子類別。
  • 靈活度受限:流程結構在編譯期固定,執行期難以動態改變步驟順序。
  • 違反里氏替換原則風險:若子類別實作違背基類別協定,可能導致錯誤。

適用場景

  • 多個子類別有共同的演算法骨架,僅細節不同。
  • 需控制子類別擴展點,只允許在特定步驟客製化。
  • 重構時提取重複程式碼至基類別,將差異點抽象化。

總結

模板方法模式是繼承體系中「複用與擴展」平衡的經典實踐。本範例以權限驗證+資料查詢為例,展示如何將不變流程封裝於基類別 TemplateMethodGet(),將變化查詢來源延遲至 SqlMessage、XmlMessage 實作。掌握此模式,能讓你在設計框架、庫或業務流程時,建立出「結構穩固、擴展靈活」的程式碼架構,有效應對「流程固定、細節多變」的業務挑戰。


參考資源:DoFactory Template Method Pattern

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved